[Node.js] AWS Lambda関数の同期呼び出しを非同期に行いたい

2023.02.18

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 Delivery部の若槻です。

今回は、AWS Lambda関数の同期呼び出しを非同期に行う方法を確認してみました。

やりたいこと

具体的にやりたいことは次の通りです。Lambda関数の挙動をコードでテストするのが目的です。

  1. Lambda関数を同期的に呼び出し
  2. 1の2秒後に別の処理を実行
  3. 1の呼び出しのレスポンスペイロードを取得

1と3の間に2を行いため、1と2の処理を非同期で実行する必要があります。

Promise.all()を使えば良さそう

複数の処理を非同期で実行しつつ実行結果を取得したい場合はPromise.all()を使うと良さそうです。

Promise.all()は複数のPromiseオブジェクトを配列で指定し、全てのPromiseが解決できたらそれぞれの戻り値を配列で返します。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// Array [3, 42, "foo"]

また「2. 1の2秒後に別の処理を実行」はsetTimeout()を使うと良さそうです。

setTimeout(code, delay)

やってみた

Lambda関数のハンドラー。(実際のものより簡略化しています)

lib/cdk-sample-app.nyaoFunc.ts

export const handler = async (): Promise<string> => {
  await new Promise((r) => setTimeout(r, 5000)); // Sleepを5秒入れて、1と3の間に2を行うようにする

  return 'aaa';
};

Lambda呼び出しのレスポンスペイロードを取得するスクリプト。

script.ts

import {
  InvocationType,
  InvokeCommand,
  LambdaClient,
} from '@aws-sdk/client-lambda';

const lambdaClient = new LambdaClient({
  region: 'ap-northeast-1',
});

const main = async (): Promise<void> => {
  const promiseResults = await Promise.all([
    // 1. Lambda関数を同期的に呼び出し
    lambdaClient.send(
      new InvokeCommand({
        FunctionName: 'nyaoFunc',
        InvocationType: InvocationType.RequestResponse,
      })
    ),

    // 2. 1の2秒後に別の処理(省略)を実行
    setTimeout((r) => r, 2000),
  ]);

  const lambdaResponse = promiseResults[0];

  // 3. 1の呼び出しのレスポンスペイロードを取得
  console.log(Buffer.from(lambdaResponse.Payload!).toString());
};

main();

スクリプトを実行すると、Lambda関数の実行時間5秒を経てレスポンスペイロードを取得できました。

$ time npx ts-node script.ts                 
"aaa"
npx ts-node script.ts  1.59s user 0.15s system 26% cpu 6.568 total

参考

以上