在 JavaScript 中,在循环中使用 await 会阻塞循环吗?

新手上路,请多包涵

采取以下循环:

 for(var i=0; i<100; ++i){
    let result = await some_slow_async_function();
    do_something_with_result();
}

  1. await 是否阻塞循环?或者 iawait ing 时继续递增?

  2. do_something_with_result() 的顺序是否保证顺序 i ?还是取决于 await ed 函数对每个 i 有多快?

原文由 smerg 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答
  1. await 是否阻塞循环?或者 iawait ing 时继续递增?

“块”不是正确的词,但是是的, 在等待时不会继续递增。相反,执行跳回到 async 函数被调用的地方,提供一个 promise 作为返回值,继续函数调用之后的其余代码,直到代码堆栈被清空。然后当等待结束时,函数的状态被恢复,并在该函数内继续执行。每当该函数返回(完成)时,相应的 promise —— 之前返回的 —— 就被解决了。

  1. do_something_with_result() 的顺序是否保证顺序 i ?还是取决于 await ed 函数对每个 i 有多快?

订单有保证。 await 之后的代码也保证仅在调用堆栈清空后执行,即至少在下一个微任务可以执行时或之后执行。

查看此代码段中的输出结果。特别注意它说“调用测试后”的地方:

 async function test() {
    for (let i = 0; i < 2; i++) {
        console.log('Before await for ', i);
        let result = await Promise.resolve(i);
        console.log('After await. Value is ', result);
    }
}

test().then(_ => console.log('After test() resolved'));

console.log('After calling test');

原文由 trincot 发布,翻译遵循 CC BY-SA 3.0 许可协议

正如@realbart 所说,它确实阻止了循环,然后循环将使调用顺序进行。

如果你想触发大量可等待的操作,然后一起处理它们,你可以这样做:

 const promisesToAwait = [];
for (let i = 0; i < 100; i++) {
  promisesToAwait.push(fetchDataForId(i));
}
const responses = await Promise.all(promisesToAwait);

原文由 Kris Selbekk 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题