0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【備忘録】Promise.allの引数をflatMapで作成する

Posted at

背景

"awaite Promise.ALL"と"flatMap"メソッドを用いて、引数に設定した全てのPromseオブジェクトにおける非同期処理のresolveを待つ処理を書くことがあったので備忘録としてまとめます。

Promise.ALLとは

Promise.ALLは、引数に設定してるPromiseオブジェクトを返す非同期関数の全ての結果がresolveになった際、結果を返すというものです。

基本構文

index.js
Promise.all([promise1, promise2, promise3])
  .then((results) => {
    console.log(results);
  })
  .catch((error) => {
    console.error(error);
  });

今回は上記のpromise1, promise2, promise3をflatMapで作成していきます。

flatMapとは

flatMapとは、mapのような形で、配列をループして新しい配列を組み直すものではあるのですが、「ネストされた値」を一次元(フラット)にして組み直すものとなります

mapとの違い

index.js
      // map
      const arr = [[1, 2], [3, 4], [5]];

      const newArr = arr.map((item) => {
        return (item = item.map((i) => {
          return i * 2;
        }));
      });

      console.log(newArr);

      // 出力結果
      // [ [ 2, 4 ], [ 6, 8 ], [ 10 ] ]

      // flatMap
      const testArr = [[1, 2], [3, 4], [5]];

      const newTestArr = testArr.flatMap((item) => {
        return (item = item.flatMap((i) => {
          return i * 2;
        }));
      });

      console.log(newTestArr);

      // 出力結果
      // [ 2, 4, 6, 8, 10 ]

このように処理後の結果がフラットになります。

想定

下記のように、"連続的な接頭辞_ID_何かしらの情報"をプロパティとし各種値がある形としたものがリクエストデータに格納されているとします。

index.js
const obj = {
  itemsA_1_name: "Aのアイテム1",
  itemsA_1_number: 10,
  itemsA_2_name: "Aのアイテム2",
  itemsA_2_number: 20,
  itemsB_1_name: "Bのアイテム1",
  itemsB_1_number: 30,
  itemsB_2_name: "Bのアイテム2",
  itemsB_2_number: 40,
  itemsC_1_name: "Cのアイテム1",
  itemsC_1_number: 50,
  itemsC_2_name: "Cのアイテム2",
  itemsC_2_number: 60,
};

上記からIDのみを抽出し、かつカテゴリー別の配列(今回で言うとA〜C)を作成し、それを元に取得した値を各種任意のテーブルにインサートしていくといった形なのですが、今回は簡易的にコンソールに出力する形とします。

実装

上記のオブジェクトからキーを取り出し、そのキーを引数として値の配列を取得し、その配列に対してmapでPromiseオブジェクトを返す関数を作成します

index.js
const obj = {
  itemsA_1_name: "Aのアイテム1",
  itemsA_1_number: 10,
  itemsA_2_name: "Aのアイテム2",
  itemsA_2_number: 20,
  itemsB_1_name: "Bのアイテム1",
  itemsB_1_number: 30,
  itemsB_2_name: "Bのアイテム2",
  itemsB_2_number: 40,
  itemsC_1_name: "Cのアイテム1",
  itemsC_1_number: 50,
  itemsC_2_name: "Cのアイテム2",
  itemsC_2_number: 60,
};

// プレフィックスを元に値を取得する為のカテゴリリスト
const categoryList = ["A", "B", "C"];

const testFn = async () => {
  // 他の処理が実行される
  console.log("start");

  // 全ての非同期処理が終わるまで待つ
  await Promise.all(
    // カテゴリリストを元にflatMapを使用して一次元配列に変換
    categoryList.flatMap((category) => {
      // オブジェクトのキーを元にアイテムIDを取得
      const itemIds = Object.keys(obj)
        .filter((key) => key.startsWith(`items${category}_`) && key.endsWith(`_name`))
        .map((key) => key.split("_")[1]);
      
      // アイテムIDを元にオブジェクトのプロパティ名を取得して、それを元にブラケット方式でオブジェクトにアクセスし、アイテムの名前と数を出力
      return itemIds.map(async (id) => {
        try {
          console.log(`アイテムの名前は: ${obj[`items${category}_${id}_name`]}`);
          console.log(`アイテムの数は: ${obj[`items${category}_${id}_number`]}`);
        } catch (error) {
          console.error(error);
        }
      });
    })
  );

  // 上記が完了次第、他の処理が実行
  console.log("end");
};

testFn();

// コンソールの結果
// start
// アイテムの名前は: Aのアイテム1
// アイテムの数は: 10
// アイテムの名前は: Aのアイテム2
// アイテムの数は: 20
// アイテムの名前は: Bのアイテム1
// アイテムの数は: 30
// アイテムの名前は: Bのアイテム2
// アイテムの数は: 40
// アイテムの名前は: Cのアイテム1
// アイテムの数は: 50
// アイテムの名前は: Cのアイテム2
// アイテムの数は: 60
// end

これにて、各種オブジェクトの値を取得することができました。
リクエストボディから特定のプロパティを取得してインサート時のプリペアドステートメントとして活用できます。

まとめ

まとまった接頭辞とIDが付与されたオブジェクトがリクエストに入っている場合、上記の方法で取り出せます。
また、接頭辞をまとめた配列を作成し、それを元に非同期処理を行う場合はPromise.ALLとflatMapの相性が良いと感じましたので、ひとつの手札として覚えておきたいと思いました。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?