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