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

smo*_*rgs 50 javascript async-await

采取以下循环:

for(var i=0; i<100; ++i){
    let result = await some_slow_async_function();
    do_something_with_result();
}
Run Code Online (Sandbox Code Playgroud)
  1. 是否await阻止循环?或者i继续await增加?

  2. 关于do_something_with_result()保证顺序的顺序是i什么?或者它取决于awaited函数对每个函数的速度有多快i

tri*_*cot 49

  1. 是否await阻止循环?或者i继续await增加?

"阻止"不是正确的词,但是,是的,等待时不会继续增加.相反,执行会跳回到async调用函数的位置,提供一个promise作为返回值,继续执行函数调用之后的其余代码,直到代码堆栈被清空为止.然后当等待结束时,恢复功能的状态,并在该功能内继续执行.只要该函数返回(完成),就会解析之前返回的相应promise.

  1. 关于do_something_with_result()保证顺序的顺序是i什么?或者它取决于awaited函数对每个函数的速度有多快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');
Run Code Online (Sandbox Code Playgroud)

  • @smorgs 堆栈解释实际上更多地与标准承诺“then”行为有关,而不是与生成器有关。只有“跳回调用的地方”和“恢复函数的状态”才是“yield”。 (2认同)

Kri*_*ekk 9

正如@realbart所说,它确实阻止了循环,然后循环使调用成为顺序.

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

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

  • 这个答案实际上并没有回答这个问题 (3认同)

mza*_*zar 8

您可以在"FOR LOOP"中测试async/await,如下所示:

(async  () => {
        for (let i = 0; i < 100; i++) {
                await delay();
                console.log(i);
        }
})();

function delay() {
        return new Promise((resolve, reject) => {
                setTimeout(resolve, 100);
        });
}
Run Code Online (Sandbox Code Playgroud)