async/awaitでPromiseの待ち合わせを行う

async/awaitでPromiseの待ち合わせを行う:

もう語り尽くされた感もあるのですが、async/awaitで複数のPromiseを待ち合わせる場合のやり方についてです。

Chrome 69のDevToolsのコンソールで動作確認を行いました。


3行で


  • Promise.all() を使う方法があるよね
  • awaitの配列を作る方法もあるみたいなんだ
  • おもしろいね(小並感)


Promise.all()をawaitする

筆者がよくやるのは、Promise.all()をawaitする方法です。

Promise.all()をawaitする方式
async function hoge() { 
    const start = Date.now(); // 時間計測用 
 
    // sleep的なやつ 
    const p11 = new Promise(resolve => setTimeout(resolve, 1000)); 
    const p12 = new Promise(resolve => setTimeout(resolve, 2000)); 
    const p13 = new Promise(resolve => setTimeout(resolve, 3000)); 
 
    // 結果を待ち合わせる 
    const [r11, r12, r13] = await Promise.all([p11, p12, p13]); 
 
    // 経過時間を表示 
    console.log("time", Date.now() - start); 
} 
hoge(); 
 
=> time 3005 
逐次に実行されたら6秒かかる処理ですが、並行で実行されてくれたようで、3秒で終わっています。

p11〜p13の結果が出揃った時点で結果が出るので、待ち合わせをしたい場合には、これでよさそうです。


awaitの配列を作る

さて、こんな話を同僚の @kaminchu にしてみたところ、

const [r11, r12, r13] =[await p11, await p12, await p13]; 
でいけるかも・・・?
というコメントをいただきまして、「流石にそれは逐次で実行されるやろー」と思いながら試してみました。

awaitの配列を作る方式
async function fuga() { 
    const start = Date.now(); // 時間計測用 
 
    // sleep的なやつ 
    const p21 = new Promise(resolve => setTimeout(resolve, 1000)); 
    const p22 = new Promise(resolve => setTimeout(resolve, 2000)); 
    const p23 = new Promise(resolve => setTimeout(resolve, 3000)); 
 
    // 結果を待ち合わせる 
    const [r21, r22, r23] = [await p21, await p22, await p23]; 
 
    // 経過時間を表示 
    console.log("time", Date.now() - start); 
} 
fuga(); 
 
=> time 3003 
並行処理になってる……!!!!

動いちゃった以上は疑いようがないですが、評価順が謎です。もともとそういう仕様なんでしょうけれども、意外でした。疑ってごめんよ……


両者の違い

記述量だったり見た目の違いというのはあるのですが、挙動としてはあまり違いがないので、好きな方を使えばよさそう、というのが正直なところです。


追記

と思っていましたが、全然違う挙動でした。

コメント欄でご指摘いただきましたが、awaitを配列にするやり方は、

const p21 = new Promise(resolve => setTimeout(resolve, 1000)); 
const p22 = new Promise(resolve => setTimeout(resolve, 2000)); 
const p23 = new Promise(resolve => setTimeout(resolve, 3000)); 
の時点で並行処理が始まっているので、これだと

const p21 = new Promise(resolve => setTimeout(resolve, 1000)); 
const p22 = new Promise(resolve => setTimeout(resolve, 2000)); 
const p23 = new Promise(resolve => setTimeout(resolve, 3000)); 
 
const r21 = await p21; 
const r22 = await p22; 
const r23 = await p23; 
とあまり変わりません。

筆者は Promise.all() を使う感じになりそうです。


まとめ

async/awaitは奥が深いですね(小並感)

コメント

このブログの人気の投稿

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-04-30 23:37:32 RSSフィード2021-04-30 23:00 分まとめ(42件)

投稿時間:2023-02-05 02:09:04 RSSフィード2023-02-05 02:00 分まとめ(9件)