18
12

More than 5 years have passed since last update.

Promise.all()という選択肢

Last updated at Posted at 2017-09-01

はじめに

「AWS-SDK for Node」を利用してよくAWSのサービスを利用しているのですが、基本的にPromiseを使ってリクエストを投げてます。そんなとき配列を一行ごとにPromiseで処理しなければならん事案が発生したので、そういや「Promise.all()」とかあったなーと思いつつ、教えてもらったりしたので備忘録的に残しておく(すんごい今更だろうけど)

やりたいこと

data.json
[
  {"id": "aaa", "value": "1234"},
  {"id": "bbb", "value": "3456"},
  {"id": "ccc", "value": "5678"}
]

上記のようなJSON配列を1行ごとにDynamoDBにPUTしていきたかった。

実際に書いてみた

main.js
const AWS = require("aws-sdk");
const co = require("co");
const dynamodb = new AWS.DynamoDB.DocumentClient({
  region: "ap-northeast-1"
});
const dynamoPutData = require("./dynamo_put_data")

co(function *(){
  data = [
    {"id": "aaa", "value": "1234"},
    {"id": "bbb", "value": "3456"},
    {"id": "ccc", "value": "5678"}
  ];
  Object.keys(data).foreach((key) => {
    const item = data[key];
    return yield dynamoPutData.putDynamoDB(dynamodb, item);
  });
}).then(() => {
  console.log("success");
}).catch((err) => {
  console.log(err);
});
dynamo_put_data
class dynamoPutData {
  /**
   * @param {DocumentClient} dynamoDB
   * @param item
   * @returns {Promise}
   */
  static putDynamoDB(dynamoDB, item) {
    return new Promise((resolve, reject) => {

      console.log("put");

      const params = {
        TableName: "foobar-json",
        Item: item
      };
      console.log(params);
      return dynamoDB.put(params, (err, data) => {
        if (err) {
          console.log(err);
          return reject(err);
        } else {
          console.log(data);
          return resolve(data);
        }
      });
    });
  }
}

まぁこんな書き方したら間違いなく怒られる
だってforeachの中でpromiseを返そうとしているから
シンタックスエラーとかがエラー文に並ぶのではないかな

そんなあなたにPromise.all()ですよ

Promise.all()を使って書くとこうなる

main.js
const AWS = require("aws-sdk");
const co = require("co");
const dynamodb = new AWS.DynamoDB.DocumentClient({
  region: "ap-northeast-1"
});

co(function *(){
  data = [
    {"id": "aaa", "value": "1234"},
    {"id": "bbb", "value": "3456"},
    {"id": "ccc", "value": "5678"}
  ];
  // Promiseの処理を配列に格納
  const promises = Object.keys(data).map((key) => {
    const item = data[key];
    return dynamoPutData.putDynamoDB(dynamodb, item);
  });
  // promisesを実行
  return yield Promise.all(promises);
}).then(() => {
  console.log("success");
}).catch((err) => {
  console.log(err);
});

あらかじめpromisesにPromiseの配列を用意しておいて、Promise.all()で実行させることによって、promisesの処理を実行し、すべての処理が終わるまで次の処理を待ってくれます
これでJSON配列をPromiseで処理させることができました

まとめ

やりたいとこはこれで叶ったわけですが、非同期で処理をしているので、扱うデータによってはこれでは問題が発生してしまうことがあります。たとえば、時系列順での扱いがすごく重要なデータの場合などなど。ちゃんと時系列順に処理が完了しているかは保証がないですからね・・・そういうときにはひと工夫が必要ですね

ではまた!

18
12
3

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
18
12