Sunday, 9 April 2017

How can I process asynchronous results in order as soon as they resolve in JavaScript?

I have an asynchronous function that takes quite a bit of time to call back, that needs to run for an array of inputs, and pipe the results to subsequent operations. My initial approach was Promise-based:

Promise.all(entries.map((entry) => {
  return new Promise((resolve, reject) => {
    processEntry(entry, resolve);
  });
})).then((outputs) => {
  outputs.forEach((output) => {
    return console.log(output);
  });
  callback();
});

The issue with this, is that the outputs only get processed (or in this case logged) after all of them have resolved. In order to have them log as soon as they've resolved, I tried this more old-fashioned approach:

var i = 0;
entries.forEach((entry) => {
  processEntry(entry, (output) => {
    console.log(output);
    if (++i >= entries.length)
      callback();
  });
});

This works for my very particular case, but doesn't seem like a correct general solution, since there's no longer any guarantee that the outputs will be in order.

The best way I can think of so far to achieve the desired effect, is to populate an array with the outputs at their original index in entries, and every time a new output comes, you process the outputs from the start of the array with a separate sliding index that stops when it reaches an undefined.

Is there a more elegant way to achieve this?



via Paraknight

No comments:

Post a Comment