Home > Software engineering >  How to supply metadata about the promises when calling Promise.all()?
How to supply metadata about the promises when calling Promise.all()?

Time:09-22

I'm working on some Javascript code that looks like this:

const arrayOfPromises = getArrayOfPromises();
Promise.all(arrayOfPromises).then(array => doStuff(array));

I need to change getArrayOfPromises() to return some information about each promise - for simplicity, let's say it's a simple true/false flag for each. My first instinct was to refactor this function to return an array of objects instead, e.g:

const getArrayOfObjects = () => {
    ...
    return [
             { promise: promise1, flag: flag1 },
             { promise: promise2, flag: flag2 },
             ...
             { promise: promisen, flag: flagn }
           ];
}

However, the above wouldn't work with Promise.all because it only works directly with an iterable of Promise objects without the wrapper objects in between.

What's the simplest way to supply such metadata for each of the promises and then work with it once all the promises have been resolved?

CodePudding user response:

If you want to use this meta data once the promises have been resolved and you don't have any control over the values that are being resolved by the promises returned from getArrayOfPromises(), then you can simply call then() on every separate promise in the array and make it return the original value combined with your meta data. Though make sure you replace the original promise with the promise returned by the .then(). Array.prototype.map() makes this easy:

arrayOfPromises = arrayOfPromises.map(promise => promise.then(value => ({
  value,
  flag: true
})));

Example:

let arrayOfPromises = getArrayOfPromises();
arrayOfPromises = arrayOfPromises.map(promise => promise.then(value => ({
  value,
  flag: true
})));

Promise.all(arrayOfPromises).then(array => doStuff(array));

function getArrayOfPromises() {
  return [sleep(1000), sleep(1500), sleep(2000)];
}

function doStuff(array) {
  console.log(array);
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(() => resolve('resolved after '   ms), ms));
}

If you do have control over what getArrayOfPromises() returns, then simply return the meta data as part of the value that is being resolved.

CodePudding user response:

What's the simplest way to supply such metadata for each of the promises and then work with it once all the promises have been resolved?

Just put the data in each result value. It's not metadata about the promise, but about the value (?), and you don't need to work with it until all promises are resolve, so the results are the perfect place. The flags just become contents of the array that Promise.all(…) resolves to.

  • Related