1. ホーム
  2. javascript

[解決済み] JavaScriptで、ループの中でawaitを使用するとループがブロックされるのですか?

2023-01-10 04:08:22

質問

次のようなループを考えてみましょう。

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

  1. await はループをブロックしているのでしょうか?それとも i はインクリメントされ続け、その間 await になっているのでしょうか?

  2. の順序は正しいですか? do_something_with_result() に関して順次保証されているか? i ? それとも await ed 関数が各 i ?

どのように解決するのですか?

<ブロッククオート
  1. await はループをブロックするのでしょうか?それとも i はインクリメントされ続け、その間 await になっているのでしょうか?

block"は適切な表現ではありませんが、そうです。 i は待機中にインクリメントされ続けません。その代わり、実行は async 関数が呼び出された場所にジャンプし、戻り値としてプロミスを提供し、関数呼び出しの後に続く残りのコードを、コードスタックが空になるまで継続します。そして、待ち受けが終わると、関数の状態が復元され、その関数内で実行が継続されます。その関数が戻る(完了する)たびに、先に返された対応する約束が解決されます。

  1. の順序は do_something_with_result() に関して順次保証されているか? i ? それとも await ed 関数が各 i ?

順番は保証されています。に続くコードは await に続くコードも、コールスタックが空になった後、つまり少なくとも次のマイクロタスクが実行できる時かその後にのみ実行されることが保証されます。

このスニペットで出力がどのようになっているかを見てください。特に、"after calling test"と書かれているところに注意してください。

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');