👻
[JavaScript] forEachでasync/awaitは使える
JavaScript の forEach で async/await は使える
JavaScrript の forEach で async/await が使えないという誤解が一部あるようですが、全く問題なく使えます。そういう誤解が何故発生してしまうかと言えば、非同期を同期させるための管理を行っていないからです。プログラムは思った通りではなく書いたとおりに動きます。同期させるようにプログラムを書かなければ、その通りの結果が返ってきます。使えないのではなく使っていないのが原因です。
forEach で非同期を同期させるプログラムを作る
配列の内容を 1 秒ごとに一つ表示させるプログラムを forEach で作ってみます。
- こちらに実行環境を用意しました
- プログラム内容
// 疑似セマフォによるスケジューラ
const semaphore = (
limit = 1,
count = 0,
rs = new Array<() => void>(),
all?: () => void
) => ({
acquire: () =>
++count > limit && new Promise<void>((resolve) => rs.push(resolve)),
release: () => (--count ? rs.shift()?.() : all?.()),
all: () => count && new Promise<void>((resolve) => (all = resolve)),
});
const main = async () => {
const s = semaphore(); //引数に2以上を設定するとその数だけ並列で実行
["A", "B", "C", "D"].forEach(async (v) => {
await s.acquire(); //セマフォカウントを増やす
console.log(v);
await new Promise((resolve) => setTimeout(resolve, 1000)); //1秒待つ
s.release(); //セマフォカウントを減らす
});
await s.all(); //全ての終了を待つ
console.log("end");
};
main();
- 出力結果
A
B
C
D
end
ということで何の問題も無く順番通りに動作しました。
まとめ
JavaScript の forEach で async/await は使えます。
Discussion