最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using AsyncAwait vs Promise.all with for-loops - Stack Overflow

programmeradmin9浏览0评论

Here is how I understand things currently:

async/await in a for-loop should pause execution until the promise resolves, meaning that the next iteration of the loop won't occur until that line finishes.

Consider the following array:

const data = [];
for (let i = 0; i <= 100000; i++) {
    data.push(i);
}

Method 1: Awaiting Promises in a for-loop

async function method1() {
  const startTime = new Date();
  console.log('start:', startTime);

  for (const item in data) {
    await new Promise(resolve => {
      if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
    });
  }

  const endTime = new Date();
  console.log('finish:', endTime);
  console.log('total time:', endTime-startTime);
}

Because it requires sequential execution of promises to continue through the loop, I figured using Promise.all would be a performance enhancement that leverages asynchronous processing to a greater degree:

Method 2: Promise.all following a for-loop

async function method2() {
  const promises = [];
  const startTime = new Date();
  console.log('start:', startTime);

  for (const item in data) {
    const promise = new Promise(resolve => {
      if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
    });

    promises.push(promise);
  }

  await Promise.all(promises);
  const endTime = new Date();
  console.log('finish:', endTime);
  console.log('total time:', endTime-startTime);
}

My reasoning: the loop would continue to bang out new Promises while each previously created Promise attempts resolve. So in my head, method 1 = blocking... while method 2 = less blocking.

When I run these both on repl.it, I found that method method 1 is actually quicker, almost by a factor of 2. Can somebody explain why this is? Shouldn't it be the other way around?

Here is how I understand things currently:

async/await in a for-loop should pause execution until the promise resolves, meaning that the next iteration of the loop won't occur until that line finishes.

Consider the following array:

const data = [];
for (let i = 0; i <= 100000; i++) {
    data.push(i);
}

Method 1: Awaiting Promises in a for-loop

async function method1() {
  const startTime = new Date();
  console.log('start:', startTime);

  for (const item in data) {
    await new Promise(resolve => {
      if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
    });
  }

  const endTime = new Date();
  console.log('finish:', endTime);
  console.log('total time:', endTime-startTime);
}

Because it requires sequential execution of promises to continue through the loop, I figured using Promise.all would be a performance enhancement that leverages asynchronous processing to a greater degree:

Method 2: Promise.all following a for-loop

async function method2() {
  const promises = [];
  const startTime = new Date();
  console.log('start:', startTime);

  for (const item in data) {
    const promise = new Promise(resolve => {
      if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
    });

    promises.push(promise);
  }

  await Promise.all(promises);
  const endTime = new Date();
  console.log('finish:', endTime);
  console.log('total time:', endTime-startTime);
}

My reasoning: the loop would continue to bang out new Promises while each previously created Promise attempts resolve. So in my head, method 1 = blocking... while method 2 = less blocking.

When I run these both on repl.it, I found that method method 1 is actually quicker, almost by a factor of 2. Can somebody explain why this is? Shouldn't it be the other way around?

Share Improve this question edited Jun 5, 2020 at 17:02 stoneb asked Jun 5, 2020 at 16:56 stonebstoneb 531 silver badge5 bronze badges 1
  • 1 The conceptual difference between the two approaches is that one runs the asynchronous operations in parallel, the other runs them in serial. With fake asynchronous operations, you can't see the real effect of that difference. With real asynchronous operations, the effect would be obvious and running in parallel would have a way faster end-to-end time. If each asynchronous operation took 200ms to resolve, then method 1 would resolve in ~n * 200ms and method 2 would resolve in ~200ms where n is the number of async operations you run. – jfriend00 Commented Jun 5, 2020 at 17:52
Add a ment  | 

2 Answers 2

Reset to default 3

My guess is that you resolve too fast, so the looping dominates the execution time, since method2 has two loops: one to push to the array and one for promise.all to plete while method1 only has one loop, so your feeling "almost a factor of two" is actually theoretically correct.

Try faking an actual async operation like new Promise(resolve => setTimeout(resolve, 200)) and you should get what you expected

To add further to what Drake said. The only reason why method 2 is slower without timeouts is because of the number of loops it will have to encounter, but in a real scenario where request or asynchronous operations have delays. Method 2 will most of the time be faster

Here is the modified snippet with SetTimeout.

const data = [];
for (let i = 0; i <= 1000; i++) {
    data.push(i);
}


async function method1() {
  const startTime = new Date();
  console.log('start 1:', startTime);

  for (const item in data) {
   await new Promise(resolve => {
      setTimeout(()=>{
        if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
      },1)
    });
  }
  const endTime = new Date();
  console.log('finish 1:', endTime);
  console.log('total time:', endTime-startTime);
}

async function method2() {
  const promises = [];
  const startTime = new Date();
  console.log('start 2:', startTime);

  for (const item in data) {
    const promise = new Promise(resolve => {
      setTimeout(()=>{
        if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
      },1)
    });

    promises.push(promise);
  }

  await Promise.all(promises);
  const endTime = new Date();
  console.log('finish 2:', endTime);
  console.log('total time:', endTime-startTime);
}

method1()
method2()

发布评论

评论列表(0)

  1. 暂无评论