Skip to content Skip to sidebar Skip to footer

Array Of Promise With Results Separately

Basically, I'm looking for something like Promise.all(), but one that calls the function in then() for each result, as soon as that result is ready. It's trivial to write using sta

Solution 1:

Just use map:

letread = file => returnnewPromise(resolve => {
  const fr = newFileReader();
  fr.onload = e =>resolve(e.target.result);
  fr.readAsDataURL(file);
});

Promise.all(files.map(file =>read(file).then(bar)))
  .then(allResultsFromBar => { /* use results array */ });

Note that .then promotes anything returned from a function it executes to a promise (i.e. it calls Promise.resolve on it implicitly), so Promise.all is guaranteed to receive an array of promises no matter what bar returns.

Solution 2:

Working from @jib's answer and the comment :

I want to have a function readFiles that takes a list of files as its only argument, and I want it to return some kind of promise that I could call then() on, and the function that I would put in then() would be called separately for each of the files.

That's not quite possible because a .then() callback is only called once, not once per result delivered by Promise.all().

This is close :

letread = file => returnnewPromise((resolve, reject) => {
    const fr = newFileReader();
    fr.onload = e =>resolve(e.target.result);
    fr.onerror = reject; // don't forget to reject on error
    fr.readAsDataURL(file);
});

letreadFiles = files => returnPromise.all(files.map(read)); // <<<<< this is the line you seek

Allowing you to write :

const files = ["...", "...", "..."];
readFiles(files)
.then(allFileResults => allFileResults.map(bar)); // bar is your function for processing file results// possibly chain another .then() if required to observe/process bar()'s results

Thus bar() will operate on each of the file contents in turn.

However, in getting the code as close as possible to what you asked for :

  • your "as soon as" requirement isn't truly meet; the allFileContents.map(bar) process is downstream of Promise.all(), therefore waits for all files to be read before commencing the bar() calls.
  • any single error in readFiles(...) will (without some sort of error recovery) scupper the whole enterprise; allFileContents.map(bar) would never be called on any of the files; that may be good or bad depending on your application; good news though, error recover is easily inserted.
  • as written, bar() must be synchronous; if not, you can simply insert another Promise.all(), ie allFileResults => Promise.all(allFileResults.map(bar)).

For these reasons, @jib's solution may well be the one to go for but it depends on what the application demands.

Post a Comment for "Array Of Promise With Results Separately"