AWS SDKのリソースのリスト取得系のAPIでは、「ある程度の塊で結果を返すけど、全部返しきれない場合はtokenも返すので、次回はそのtokenを使って呼んでくれたら続きを返すよ」という物が多いです。
var params = {
Marker: 'STRING_VALUE',
MaxItems: 0,
PathPrefix: 'STRING_VALUE'
};
iam.listRoles(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
callbackのパラメータ
- IsTruncated — (Boolean)
- A flag that indicates whether there are more items to return.
〜略〜
- Marker — (String)
- When IsTruncated is true, this element is present and contains the value to use for the Marker parameter in a subsequent pagination request.
callbackのパラメータのIsTruncateがtrueだったら、全部を返していないので次回呼び出し時にMarkerをパラメータにセットしてlistRoles()を呼ぶ必要があります。
これをPromiseを使っていい感じに書いてみます。
しばり
- バベらない
- Lambdaのコンソールにそのまま書ける
実装
const listIAMRoles = () => new Promise( // 1
(resolve, reject) => {
const iam = new AWS.IAM();
const result = [];
const loop = (marker) => {
iam.listRoles({
Marker: marker // 3
}).promise() // 4
.then((data) => {
data.Roles.map((role) => { // 6
result.push({
roleName: role.RoleName,
arn: role.Arn,
path: role.Path
});
});
if (data.IsTruncated) { // 7
loop(data.Marker);
} else {
resolve(result); // 8
}
})
.catch(reject); // 5
};
loop(); // 2
}
);
実装の説明
- listIAMRoles()がPromiseを返すようにします。
- まず、markerを引数に取るloop()関数を定義し、初回分として引数無しでloop()を呼び出します。
- loop()の引数をMakerプロパティにセットしてIAM#listRoles()を呼び出します。
- 初回は引数markerがundefinedなので、listRoles()はMarkerがセットされずに呼ばれます。
- IAM#listRoles()の戻り値のPromiseを取得します。
- IAM#listRoles()が失敗した場合、.catch()に処理が進むので、そのままreject()を呼び出します。
- reject()の引数にはIAM#listRoles()でのエラーが渡されるので、このlistIAMRoles()の呼び出し元の.catch(fn)の引数に渡されます。
- .then(fn)の引数にIAM#listRoles()の結果が渡されるので、任意に処理します。
- data.IsTruncatedがtrueの場合、まだIAM#listRoles()で返されるべきデータが残っているということなので、data.Makerを引数にloop()を再帰呼び出しします。
- もう残りのデータがない場合は、resolve()を呼び出して、listIAMRoles()を終了します。
Lambda内でつかう
listIAMRoles()がPromiseを返すので、こちらも.then()/.catch()で後続処理します。
exports.handler = (event, context, callback) => {
listIAMRoles()
.then((roles) => {
callback(null, roles);
})
.catch((e) => {
callback(e); // LambdaFunctionをエラーで終了する
});
};
まとめ
再帰処理をいい感じで実装できました。IAM#listRoles()以外にもこのような
出し惜しみ系APIはたくさんあるので、同じように実装できると思います。
では!