LoginSignup
78
67

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-10-17

もう語り尽くされた感もあるのですが、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

並行処理になってる……!!!!

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

両者の違い

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

追記

と思っていましたが、Promise.all()[await p1, await p2...]は全然違う挙動でした。new Promise()の式と[await p1, await p2...]を組み合わせると近い挙動にはなりますが、[await p1, await p2...]という記法自体がPromise.all()と同じ機能を持っているわけではありません。

コメント欄でご指摘いただきましたが、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は奥が深いですね(小並感)

78
67
12

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
78
67