Javascriptの非同期処理はちょっととっつきにくいです。
1つならともかく複数の非同期処理の管理となると嫌になるかもしれません。
今回は3パターンの管理をまとめます。
まずテスト用の関数を用意します。
1 2 3 4 5 6 7 |
const test = (time)=>{ return new Promise((resolve, reject) => { setTimeout(()=>{ resolve(time); },time); }); } |
これは指定時間後に時間を返すだけの関数です。
これを以下のように実行すると10秒から1秒かかるプロセスが実行されます。
1 2 3 |
for(let i=10; i>0; i--){ test(i*1000).then(r => process.stdout.write(r+",")); } |
結果は 1000,2000,3000,4000,5000,6000,7000,8000,9000,10000,
早く終わったものから表示されます。
次にasync/awaitを使って以下のように実行します。
1 2 3 4 5 6 |
(async ()=>{ for(let i=10; i>0; i--){ var r = await test(i*1000); process.stdout.write(r+","); } })(); |
結果は 10000,9000,8000,7000,6000,5000,4000,3000,2000,1000,
実行順に結果が返されます。
1つ1つの処理を待つため総実行時間に55秒かかります。
最後にPromise.all関数を使った場合です。
1 2 3 4 5 6 7 8 9 |
let ps = []; //Promise配列用 for(let i=10; i>0; i--){ ps.push( test(i*1000) ); } Promise.all(ps).then((vs)=>{ vs.forEach((v)=>{ process.stdout.write(v+","); }); }); |
結果は 10000,9000,8000,7000,6000,5000,4000,3000,2000,1000,
全ての処理が完了したときに実行されるため10秒で完了。
Promise.all() はプロミス格納順に結果を格納するため順番は保証されます。
順番が関係ない時はそのまま。
非同期処理間でパラメータの受け渡しがある場合などはasync/await。
全てが完了したときに何かをしたいときはPromise.all()。
所感
Promiseはいつのまにか必需品になってしまってますが、あんまり理解せずに使ってる気がする。今回みたいに時々整理しないと。
しかしsetIntervalで非同期処理が終わったかどうか確認していたころが懐かしい。