Node jsで始めるfilesystem9 async await配列処理

javascript

非同期処理も処理内容が増えるにつれてまとめて処理したくなるでしょう。同期処理でやっているようにforEachのように。

普通に上から下に書くだけだと冗長な処理になります。これが何十回と繰り返しになるとうんざりしますね。避けるべきでしょう。これを配列処理でまとめて処理します。

for文の中にawait構文を組み込むだけで配列の非同期処理が可能になります。但し実際実行するとわかるのですがfor文の場合逐次的に配列の中身を処理するので並列処理と比べて遅くなりがちです。(このコードの場合毎回timeOut関数が終わってから次のtimeOut関数に移るので2秒+2秒+2秒の処理時間になる)並列処理で処理させたい場合は他の方法を行わなければなりません。

Promise.allは配列形式のPromiseオブジェクトを返す関数を処理するメソッドだと触れました。今回Arrayのmap関数をPromise.allの中で使用しています。さらにその中の関数でPromiseを返す関数の引数に配列の値を渡しています。このようにPromise.allをasync、awaitで囲む事でpromiseでは無い値の配列をそのまま非同期処理の関数で処理できるようになります。並列処理なのでfor文と違ってtimeOut関数、2秒の処理を同時に行って全て完了した時点で結果を返します。返したい値はそのままreturn文で返せば通常のmap関数のように配列形式で各種結果を返してくれます。ただし関数が入れ子になっているのでasync、awaitが何度か宣言されているのに気をつけてください。Promise.all自体promiseを返すメソッドなのでawaitを宣言しないといけないのとmapメソッドの中には関数が入るので必ずasyncを宣言して中の非同期処理の関数の頭にはawaitをつけてください。勿論Promise.all自体async関数の中でしか使用できません。Arrayメソッドならなんでもいけると思うかもしれませんがforEachもfilterも使えません。あくまでmapのみです。forEachのように使いたい場合も問題ないはずです。問題はその他のArrayメソッドが使いたい場合。残念ながら多少冗長になってもPromise.all mapメソッドに続けて他のarrayメソッドを続けるしかありません。

Promise.allでまず非同期処理を行って返ってきた結果をreduceメソッドでまとめています。その他のメソッドを使う場合も同じように使います。ちなみにPromise.allだけでなくallSettledも勿論使えます。

返ってきた値と同時にPromiseの状態も帰ってきました。Promise.raceもいけます。

ただし非同期処理を決まった順番に処理しないといけない場合は並行処理は思わぬ結果をもたらすので避けてください。

Beer 寄付してサイトを応援する。