[AWS] AWS SDK for javascript(Node.js)におけるPromiseの使い方

AWS SDK for javascriptを使って、AWSのリソース情報を取得し、その情報を以て何らかの処理を実行する際に、取得した結果を変数に格納して、それを表示しようとしたのですが、APIは非同期であるため、API実行と非同期で、APIの結果が帰って来る前に、変数に格納されている値が表示されてしまうので、値が取得できませんでした。

調べてみるとPromiseと言われる機能がNode.jsにあって、これを使うことによって、同期ぽく処理できるということを知りました。(Promiseの中が非同期でそれぞれ実行されるので、厳密には、同期ではない)

そこで今回は、「EBSボリュームの一覧を取得する」というの例として、Promiseを使って実装して見たいと思います。

Promiseをthenで繋ぐ書き方

一番簡単な方法がPromiseでresolveをthenで数珠つなぎに書く方法です。

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2({region: 'ap-northeast-1'});

new Promise(function(resolve, reject) {
  resolve(ec2.describeVolumes().promise());
})
.then((volumeList) => {
  console.log(volumeList);
});

resolveを空にしてthenに処理を書く

上ソースをちょっときれいに書くため、resolveは敢えて空にして処理を全てthen以降に書いてます。

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2({region: 'ap-northeast-1'});

Promise.resolve()
.then(() => {
  return ec2.describeVolumes().promise();
})
.then(response => {
  volumeList = response;
  console.log(volumeList);
});

関数化する

さらに、AWS SDKのAPIを叩く部分を関数化することで、よりシンプルになります。

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2({region: 'ap-northeast-1'});

let volumeList;

Promise.resolve()
.then(() => {
  return getEc2Volume();
})
.then(res => {
  volumeList = res;
});

function getEc2Volume() {
  return ec2.describeVolumes().promise();
}

Promise + ジェネレータ(co)を使う

個人的に一番簡潔な書き方が、Promiseとジェネレータを使って書く方法です。
yieldを関数の前に書くことで、関数のreturnが返却されるまで待機してから後続の処理をします。

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2({region: 'ap-northeast-1'});
const co = require('co');

co(function *() {
  let volumeList = yield getEc2Volume();
  console.log(volumeList);
});

function getEc2Volume() {
  return ec2.describeVolumes().promise();
}

 

以上