LoginSignup
2
1

More than 3 years have passed since last update.

Promise.all()の応用

Last updated at Posted at 2020-12-29

業務の中で触れたので、知識の定着&備忘のために記録します。

Promise.allを使って並列処理する

まずは、前提になる並列処理についてです。
itemA, itemBに代入したいデータを返すfuncA, funcBという2つの非同期関数があるとして、並列処理をしようと思うと、こうなります。

  // funcAが終わってからfuncBを処理するので処理に時間がかかる
  var itemA = await funcA();
  var itemB = await funcB();


  // 並列処理をするパターン
  var promises = [
    funcA(),
    funcB()
  ];
  var [itemA, itemB] = await Promise.all(promises);

ネストさせる

ここから、自分が直近勉強した並列処理の応用です。
以下のオブジェクトについて、firestoreからデータをフェッチして、新しい配列をつくる処理を考えます。関数の中身は適当です。
下のitemsという配列に入ってる動画とそのサムネイルのファイルを、
それぞれfirebase storageにアップロードして、帰ってきたurlをオブジェクトに紐付ける処理を考えます。

  // 対象のオブジェクト
  var items = [
    {thumbnail: file, video: file},
    {thumbnail: file, video: file},
    {thumbnail: file, video: file},
  ];

  // idからデータを取得する関数
  var uploadFile = async(file) => {
    var ref = firebase.storage().ref();
    var snapshot = await ref.child('test').put(file);
    // urlを返す
    return await snapshot.ref.getDownloadURL();
  };

やりかたはこうなります。

  //配列
  var promises = items.map(async(item) => {
    var upload_promises = [
      uploadFile(item.thumbnail),
      uploadFile(item.video)
    ];
    var [thumbnail_url, video_url] = await Promise.all(upload_promises);
    // オブジェクトとして返す
    return {thumbnail_url, video_url};
  });
  //[{thumbnail_url: 'https://~~', video_url: 'https://~~'},{...},...]が返ってくる
  var urls = await Promise.all(promises); 

この記事にあるように、forEachでasync/awaitを使うと順番が担保できなくなる、というのは知っていたので、なんとなくmapでasync/awaitを使っていいのかな、という疑問というか不安みたいなものがあったのですが、この書き方だと順番も担保されたまま並列処理ができます。

2
1
0

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
2
1