LoginSignup
48
35

More than 5 years have passed since last update.

AWS LambdaがNode.js8.10をサポートしたのでasync/awaitを試してみた

Posted at

はじめに

本日(2018/04/03)、AWSからこんなアナウンスが来ました。

やっとLambdaがNode.js8系に対応してくれましたので、早速 async/await を試してみました。

デモっていきましょう

Lambdaの作成方法は割愛します。コンソール画面から作成していただくとか、ServerlessFrameworkから作成していただくとかしてください。
ランタイムは Node.js 8.10 を指定してください。
今回のデモではDynamoDBにscanとqueryを実行するので、その権限は持っているようにIAMRoleを設定してください。

デモで使っているDynamoDBはこんな感じ

  • TableName: demo-table
  • HashKey: id
id name
1 tanaka
2 sato
3 mori

ソースコードはこんな感じ

ちなみにランタイム Node.js6.10 のときはこんな感じで書いてました。

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

exports.handler = (event, context, callback) => {
  co(function *(){
    // scanの実行
    const scanItems= yield DynamoDB.scan({TableName: "demo-table"}).promise();
    // queryの実行
    const queryItems = yield DynamoDB.query({
      TableName: "demo-table", 
      KeyConditionExpression: "#ID = :ID",
      ExpressionAttributeNames: {"#ID": "id"},
      ExpressionAttributeValues: {":ID": "1"}
    }).promise();
    return {
      scan: scanItems,
      query: queryItems
    };
  }).then(data => {
    return callback(data);
  }).catch(err => {
    return callback(err);
  });
};

上記では co モジュールを使っていますが、この場合はローカルでcoをnpm installしてZipで固めるなりしてアップロードしなければいけません。
それか

promise().then(data_1 => {
  promise().then(data_2 => {
    ...
  })
})

というような形で書くかですね…きったねぇ………
ランタイム Node.js8.10 で書くとこうなります。

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

exports.handler = async (event) => {
  try {
    // scanの実行
    const scanItems= await DynamoDB.scan({TableName: "demo-table"}).promise();
    // queryの実行
    const queryItems = await DynamoDB.query({
      TableName: "demo-table", 
      KeyConditionExpression: "#ID = :ID",
      ExpressionAttributeNames: {"#ID": "id"},
      ExpressionAttributeValues: {":ID": "1"}
    }).promise();
    // scanとqueryの結果をreturnする
    return {
      scan: scanItems,
      query: queryItems
    };
  } catch (err) {
    // エラー発生時はエラー文をreturnする
    console.error(`[Error]: ${JSON.stringify(err)}`);
    return err;
  }
};

結果

{
  "scan": {
    "Items": [
      {
        "id": "2",
        "name": "sato"
      },
      {
        "id": "1",
        "name": "tanaka"
      },
      {
        "id": "3",
        "name": "mori"
      }
    ],
    "Count": 3,
    "ScannedCount": 3
  },
  "query": {
    "Items": [
      {
        "id": "1",
        "name": "tanaka"
      }
    ],
    "Count": 1,
    "ScannedCount": 1
  }
}

さいごに

今まで非同期処理を実行するときは毎回Promiseで囲ったり、Promiseを返すようにしたり、俗に言うPromise地獄にハマることがよくあったのですが、async/awaitを使うことによって治安がよくなりそうです。

あとは現状動き続けているLambda達をメンテしていくという苦行が待っていますが、治安を守るために必要なことですので、少しづつ対応をしていこうと思います……

余談

余談ですが、上記のソースコードでわざとエラーを起こしたときに、Lambda自体は成功となっていたので、KinesisDataStreamsでLambdaがエラーのレスポンス返して来たときに再実行しているあたりがどうなるのか検証必要ですね…
おそらく明示的にエラーだよと返してあげれば良いのでしょうが…

ではまた!

48
35
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
48
35