Home > Enterprise >  How to resolve nested promises with Promise.all()
How to resolve nested promises with Promise.all()

Time:03-21

I am trying to write something like this but not able to resolve inner promises.

  const traceSamplesRequests = transactionTypes.map(async (transactionType) => {
    // This part should be synchronous since we need transactionNames
    const transactionNames = await api.getTransactionNames();
    return transactionNames.map((transactionName) => api.getTraceSamples());
  });

And I want to write with lambda functions with Promise.all not imperative loops.

CodePudding user response:

So, .map() is not promise-aware. It calls the callback and just dutifully collects the return value from the callback and advances to the next iteration of the loop. Since your callback is async with an await in it, that return value is an unresolved promise. So, what you get back from .map() is an array of promises.

So, there is no way to use .map() or any of the array iteration methods without then using something to wait for the promises.

It sounds like you already know this, but with the code you have, you would insert a Promise.all():

  const traceSamplesRequests = await Promise.all(transactionTypes.map(async (transactionType) => {
    // This part should be synchronous since we need transactionNames
    const transactionNames = await api.getTransactionNames();
    return Promise.all(transactionNames.map((transactionName) => api.getTraceSamples()));
  }));

That would get you an array of values (and the parent function would have to be async). This will run all the asynchronous operation in the loop in parallel (all in flight at the same time).

Your other choices are to use a for or while loop which will suspend loop iteration for each await and will run your asynchronous operations in sequence (second iteration of the loop not running until the first is done).

Or, you can write some sort of helper function that would be a promise-aware version of .map(). You'd probably just either use for or .map() with Promise.all() inside the helper function though.

The Async promise library has multiple such helper functions as choices to use. They are designed to work with either promises or plain callbacks.

CodePudding user response:

I actually made it work like this:


  const traceSamplesRequests = await Promise.all(
    transactionTypes.map(async (transactionType) => {
      const transactionNames = await api.getTransactionNames({ transactionType });
      return await Promise.all(transactionNames.map((transactionName) => api.getTraceSamples({ transactionType })));
    })
  );
  • Related