はじめに
「AWS-SDK for Node」を利用してよくAWSのサービスを利用しているのですが、基本的にPromiseを使ってリクエストを投げてます。そんなとき配列を一行ごとにPromiseで処理しなければならん事案が発生したので、そういや「Promise.all()」とかあったなーと思いつつ、教えてもらったりしたので備忘録的に残しておく(すんごい今更だろうけど)
やりたいこと
[
{"id": "aaa", "value": "1234"},
{"id": "bbb", "value": "3456"},
{"id": "ccc", "value": "5678"}
]
上記のようなJSON配列を1行ごとにDynamoDBにPUTしていきたかった。
実際に書いてみた
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);
});
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()を使って書くとこうなる
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で処理させることができました
まとめ
やりたいとこはこれで叶ったわけですが、非同期で処理をしているので、扱うデータによってはこれでは問題が発生してしまうことがあります。たとえば、時系列順での扱いがすごく重要なデータの場合などなど。ちゃんと時系列順に処理が完了しているかは保証がないですからね・・・そういうときにはひと工夫が必要ですね
ではまた!