Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
35
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

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

はじめに

本日(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がエラーのレスポンス返して来たときに再実行しているあたりがどうなるのか検証必要ですね…
おそらく明示的にエラーだよと返してあげれば良いのでしょうが…

ではまた!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
35
Help us understand the problem. What are the problem?