https://zenn.dev/sora_kumo/articles/612ca66c68ff52
時々ネットの解説記事で forEach は非同期だという解説を見かけますがこれは間違っています。実際の処理は逐次関数をコールバックしていくだけなので、普通に同期で動いています。コールバック中に非同期処理を使って待機動作を行っていないので、バラバラに動いているように見えるだけなのです。
ランダムに 1000ms 以内の時間を待機して文字列を出力する関数です。TypeScript になっているので、JavaScript で実行したい場合は型定義を外してください。
const f = (value: string) => {
return new Promise<void>((resolve) =>
setTimeout(() => {
console.log(value);
resolve();
}, Math.random() * 1000))
);
};
["A", "B", "C", "D", "E"].forEach((v) => {
f(v);
});
console.log("終了");
終了と表示した A~E がランダムに一気に出力されます。何も同期していません。
["A", "B", "C", "D", "E"].forEach(async (v) => {
await f(v);
});
console.log("終了");
コールバック関数を非同期にしても、結果は変わりません。非同期になるタイミングが異なるだけです。
よくあるヤツです。
const main = async () => {
await Promise.all(["A", "B", "C", "D", "E"].map((v) => f(v)));
console.log("終了");
};
main();
一応、終了が最後に来るようになりました。ただ、逐次実行はされていません。
const main = async () => {
for (const i of ["A", "B", "C", "D", "E"]) await f(i);
console.log("終了");
};
main();
逐次実行になりました。動作としてはこれで解決です。