I can fly!!

地元ITベンダー→公務員→フルリモートのフリーランス Webエンジニア もうすぐ2児の父

Promise.all()を使ってn個の非同期関数をまとめて処理する

n個の非同期関数をまとめて処理したい状況で、Promise.all()を使うことでうまく切り抜けられたのでそのメモ。

参考

developer.mozilla.org

今回出くわした状況

ソース

class hoge {
  name = null;

  constructor(name) {
    this.name = name;
  }

  // resolveを返す非同期関数
  hidouki() {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(this.name);
      }, 1000);
    });
  }
}
class fuga {
  hoges = [];

  startHoge(name) {
    this.hoges.push(new hoge(name));
  }
}

hogeクラスは時間がかかる非同期関数hidouki()を持つ。fugaクラスの startHoge() が 呼ばれるたびにhoges[]フィールドにhogeインスタンスが格納される。何度呼ばれるかはわからない。この各hogeインスタンスhidouki()をまとめて並列処理したい。

解決方法

fugaクラスにまとめて非同期処理を行うメソッドmatometeHidouki()を実装。

class fuga {
  hoges = [];

  startHoge(name) {
    this.hoges.push(new hoge(name));
  }

  matometeHidouki() {
    return new Promise(resolve => {
      // Promise.all()の引数に渡すiterableオブジェクト
      let hidoukis = [];

      // 各インスタンスのhidouki()をhidoukis[]にpushしていく
      for (const i in this.hoges) {
        hidoukis.push(
          new Promise(resolve => {
            this.hoges[i].hidouki().then(name => {
              return resolve(name);
            });
          })
        );
      }

      Promise.all(hidoukis).then(data => {
        resolve(data);
      });
    });
  }
}

呼び出し側

const fuga = new fuga();

fuga.startHoge('tarou');
fuga.startHoge('jirou');
fuga.startHoge('saburou');

fuga.matometeHidouki().then(data => {
  console.log(data);
  // expected output: Array ['tarou', 'jirou', 'saburou']
});

これで、n個の非同期関数をまとめて並列処理することができる。各resolve()の値が配列になって返ってくるので、あとは煮るなり焼くなり。。。
以上。