JavaScript 非同期 forEach
今日の投稿では、JavaScript の forEach
ループで async
を使用できるかどうかを見ていきます。 代替手段は何ですか?
JavaScript の非同期 forEach
非同期プログラミングは、Array.prototype.forEach
を対象としていません。 promise の場合と同様に、async-await
には不適切です。
const employees = await this.getEmployees();
// BAD
await employees.forEach(async (employee) => {
await giveBonusToEmployee(employee);
});
await sendEmail('All bonuses sent');
これにはいくつかの問題があります:
- 返された iterator 関数の promise は処理されません。 したがって、そのうちの 1つがエラーを起こしても気付かれません。 ノード 10 に
unhandledrejection
リスナーが登録されていない場合、プロセスはクラッシュします。 forEach
は各プロミスが 1つずつ満たされるのを待たないため、すべてのボーナスは順次ではなく同時に配布されます。 その結果、すべてのボーナスが与えられる前にループが終了します。- その結果、ボーナスが完全に提供される前に、
sendEmail()
がメールを送信します。 おそらく何も配られないでしょう。 それらはすべてエラーをスローする可能性があります!
以下は、これに対して実装できるソリューションです。
- 各ボーナスを順番に処理します。 JavaScript が
async-await
をサポートしているため、for...of
構造を使用できます。
for (const employee of employees) {
await giveBonusToEmployee(employee);
}
次のボーナスに移る前に、このループは前のボーナスが配られるのを待ちます。 必要以上に冗長になりますが、この状況では典型的な for(...;...;...)
を使用することもできます。
- すべてのボーナスを並行して処理します。
await Promise.all(employees.map(async (employee) => {
await giveBonusToEmployee(employee);
}));
順序が重要でない場合は、すべての従業員を同時に分析する方が迅速な場合があります。 これにより、すべてのボーナスが一度に配布され始めますが、すべてのボーナスが送信されるまで sendEmail()
は実行されません。
for
と while
ループは、元の関数本体に記述されているため、async-await
で自然に動作します。 ただし、別の関数を呼び出す場合、呼び出された関数が promise を返し、その promise を処理する場合にのみ、async-await
を使用できます。
.reduce()
と .map()
の両方がプロミスまたはプロミスの配列を生成するため、await
を使用できます。
ただし、ほとんどの配列メソッドは promise を返さないか、ある呼び出しから別の呼び出しに promise を渡すことができないため、それらを非同期で使用することはできません。 その結果、非同期コードを配列内で使用することはできません。たとえば、array.some()
や array.filter()
などです。
Shraddha is a JavaScript nerd that utilises it for everything from experimenting to assisting individuals and businesses with day-to-day operations and business growth. She is a writer, chef, and computer programmer. As a senior MEAN/MERN stack developer and project manager with more than 4 years of experience in this sector, she now handles multiple projects. She has been producing technical writing for at least a year and a half. She enjoys coming up with fresh, innovative ideas.
LinkedIn