📝

Node.js の Lambda で forEach を使用するときの注意点

2025/02/19に公開

Node.js の Lambda 関数ハンドラーの定義 - AWS Lambda

非同期イベントが完了するまでお待ちください。非同期イベントが完了する前に関数が戻る場合、関数が失敗したり、アプリケーションで予期しない動作が発生したりする可能性があります。これは、forEach ループに非同期イベントが含まれている場合に発生します。forEach ループは同期呼び出しを想定しています。

上記の通りです。
実際に試してみました。

試してみた

Node.js 22.x の Lambda 関数を作成、S3 バケットの情報を取得する以下のコードを実行してみました。

index.js
const { S3Client, ListObjectsV2Command } = require("@aws-sdk/client-s3");
const s3 = new S3Client();

exports.handler = async function (event) {
  const bucketList = ["bucket-1", "bucket-2", "bucket-3"];

  bucketList.forEach(async (bucket) => {
    const command = new ListObjectsV2Command({ Bucket: bucket });
    const data = await s3.send(command);
    console.log(data);
  })

  return "ok";
};

出力結果は以下の通りで、バケットの情報を出力できていません。

START RequestId: c9d1b30b-f7dd-4bc3-a9e9-1d3b3e55a548 Version: $LATEST
END RequestId: c9d1b30b-f7dd-4bc3-a9e9-1d3b3e55a548
REPORT RequestId: c9d1b30b-f7dd-4bc3-a9e9-1d3b3e55a548	Duration: 851.04 ms	Billed Duration: 852 ms	Memory Size: 128 MB	Max Memory Used: 96 MB	Init Duration: 357.33 ms

ドキュメント通りの挙動であることがわかりました。

回避策

【array-foreach-async】forEach()でasync/awaitを使おうとして失敗した皆へ #JavaScript - Qiita

forEach()の代わりにfor〜ofを使用すれば解決できました。

上記ブログに記載の通り、for...of を使用すれば非同期処理の結果を待つことができます。

index.js
const { S3Client, ListObjectsV2Command } = require("@aws-sdk/client-s3");
const s3 = new S3Client();

exports.handler = async function (event) {
  const bucketList = ["bucket-1", "bucket-2", "bucket-3"];

  for (const bucket of bucketList) {
    const command = new ListObjectsV2Command({ Bucket: bucket });
    const data = await s3.send(command);
    console.log(data);
  }

  return "ok";
};

出力結果が多いので一部のみ抜粋しますが、バケット情報を取得できました。

'$metadata': {
    httpStatusCode: 200,
    requestId: 'HVZ1920JJS80R0KP',
    extendedRequestId: '5ob6NU0rRulN4QraiNhe1UFtJ56rpH7IMoCT5zLyujG04tVuqHwzl5J25nkREDny9/7L7eY/EsQ=',
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  Contents: [
    {
      Key: 'favicon.ico',
      LastModified: 2022-05-31T00:07:33.000Z,
      ETag: '"2dac97e3bdfc1cb44fefed5dbda28664"',
      Size: 9662,
      StorageClass: 'STANDARD'
    },
以下略

まとめ

今回は Node.js の Lambda で forEach を使用するときの注意点を紹介しました。
どなたかの参考になれば幸いです。

参考資料

Discussion