Shawn Tabrizi
Shawn Tabrizi

Reputation: 12434

Output results of two promises into a single object

I have two asynchronous functions which create promises. Both functions use the same input i.

async function1(i) {}
async function2(i) {}

I will be calling these functions multiple times with different values for my input, and I want to make my code as efficient as possible, so I want to queue the promises and have them run in parallel using Promise.all().

However, I want to get a single result as my final output, which will be an array of objects like so:

[
  {
    input: i,
    result1: result1,
    result2: result2
  },
  ...
]

I have accomplished this in two descrete steps:

async function function1(i) {
  return i * i
}

async function function2(i) {
  return i * i * i
}

async function main() {
  var promises = []

  for (let i = 0; i < 10; i++) {
    let promise = function1(i)
      .then(function(result1) {
          return {i:i, result1:result1}
      });

    promises.push(promise)
  }

  var final = await Promise.all(promises)
  
  var promises2 = [];
  
  for (let i = 0; i < 10; i++) {
    let promise = function2(i)
    .then (function(result2) {
      final[i]['result2'] = result2;
    });
    
    promises2.push(promise);
  }
  
  await Promise.all(promises2)
  
  console.log(final)

}

main()

However, I feel like this can be accomplished using a single Promise.all(). Can you tell me how?

Upvotes: 0

Views: 113

Answers (2)

Shawn Tabrizi
Shawn Tabrizi

Reputation: 12434

EDIT: 333's answer is correct, not mine. This solution will have 2 batches in the queue.

I think I figured it out:

console.log("start")

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

async function function1(i) {
  await sleep(2000);
  return i * i
}

async function function2(i) {
  await sleep(2000);
  return i * i * i
}

async function main() {
  var promises = []

  for (let i = 0; i < 10; i++) {
    let a = function1(i);
    
    let b = function2(i);
    
    let promise = Promise.all([a,b]).then(
      function([resulta,resultb]) {
          return {i:i, result1: resulta, result2: resultb}
      });

    promises.push(promise)
  }

  var final = await Promise.all(promises)
  
  
  console.log(final)

}

main()

Note that I added a sleep function to test the parallelization of these functions. Everything runs in 2 seconds, so I think it is optimized.

Upvotes: 0

laptou
laptou

Reputation: 6981

async function function1(i)
{
    return i * i
}

async function function2(i)
{
    return i * i * i
}

async function main()
{
    const promises = [];

    for (let i = 0; i < 10; i++)
        promises.push(function1(i), function2(i));

    const results = await Promise.all(promises);
    const data = [];

    for (let i = 0; i < 10; i++)
    {
        const [result1, result2] = results.slice(i * 2, i * 2 + 2);
        data.push({ i, result1, result2 });
    }

    console.log(data);
}

main();

This should work smoothly and quickly. The functions function1 and function2 return Promises if you do not await them, so pushing them onto the promises array is self-explanatory.

Then you await Promise.all, which waits until all 20 promises that were fired off have completed. Finally, the second loop runs through the promises that were returned.

In my code I used destructuring assignments. I assume those are available to you since you are using async functions, which implies that you can use ES2017.

Upvotes: 1

Related Questions