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

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

Lambda 関数ハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。

次の例の関数では、イベントオブジェクトの内容をログに記録して、そのログの場所を返します。

注記

このページは、CommonJS と ES モジュールハンドラーの両方の例を示します。これらの 2 つのハンドラータイプの違いについては、「ES モジュールとしての関数ハンドラーの指定」を参照してください。

ES module handler
export const handler = async (event, context) => { console.log("EVENT: \n" + JSON.stringify(event, null, 2)); return context.logStreamName; };
CommonJS module handler
exports.handler = async function (event, context) { console.log("EVENT: \n" + JSON.stringify(event, null, 2)); return context.logStreamName; };

関数を設定すると、ハンドラー設定の値はファイル名とエクスポートしたハンドラーメソッドの名前をドットで区切ったものになります。コンソールのデフォルトと、このガイドの例では、index.handler です。これは、 handler ファイルからエクスポートされた index.js メソッドを示します。

ランタイムでは、ハンドラーメソッドに引数を渡します。最初の引数は、呼び出し元からの情報を含む event オブジェクトです。呼び出し元は、Invoke を呼び出してこの情報を JSON 形式の文字列として渡し、ランタイムはそれをオブジェクトに変換します。AWS のサービスで関数を呼び出す場合、そのイベント構造はサービスによって異なります

2 番目の引数は、コンテキストオブジェクトです。この引数には、呼び出し、関数、および実行環境に関する情報が含まれます。前述の例では、関数は、コンテキストオブジェクトからログストリームの名前を取得し、それを呼び出し元に返します。

コールバック引数を使用することもできます。これは、非同期ではないハンドラーで呼び出してレスポンスを送信できる関数です。コールバックの代わりに async/await を使用することをお勧めします。async/await により、読みやすさ、エラー処理、および効率が向上します。async/await とコールバックの違いの詳細については、「コールバックの使用」を参照してください。

命名

関数を設定すると、ハンドラー設定の値はファイル名とエクスポートしたハンドラーメソッドの名前をドットで区切ったものになります。コンソールで作成された関数のデフォルトと、このガイドの例では、index.handler です。これは、index.js または index.mjs ファイルからエクスポートされた handler メソッドを示します。

異なるファイル名または関数ハンドラー名を使用してコンソールで関数を作成する場合は、デフォルトのハンドラー名を編集する必要があります。

関数ハンドラー名を変更するには (コンソール)
  1. Lambda コンソールの [関数] ページを開き、関数を選択します。

  2. [コード] タブを選択します。

  3. [ランタイム設定] ペインまでスクロールして、[編集] を選択します。

  4. [ハンドラー] には、関数ハンドラーの新しい名前を入力します。

  5. [Save] を選択します。

async/await の使用

コードが非同期タスクを実行する場合は、async/await パターンを使用して、ハンドラーが実行を確実に終了するようにします。async/await は、Node.js で非同期コードを記述するための簡潔で読みやすい方法であり、ネストされたコールバックや連鎖する promise を必要としません。async/await を使用すると、非同期かつノンブロッキングでありながら、同期コードのように読み取るコードを記述できます。

async キーワードは関数を非同期としてマークし、await キーワードは Promise が解決されるまで関数の実行を一時停止します。

注記

非同期イベントが完了するまでお待ちください。非同期イベントが完了する前に関数が戻る場合、関数が失敗したり、アプリケーションで予期しない動作が発生したりする可能性があります。これは、forEach ループに非同期イベントが含まれている場合に発生します。forEach ループは同期呼び出しを想定しています。詳細については、Mozilla ドキュメントの「Array.prototype.forEach()」を参照してください。

ES module handler
例 – async/await を使用した HTTP リクエスト
const url = "https://aws.amazon.com/"; export const handler = async(event) => { try { // fetch is available in Node.js 18 and later runtimes const res = await fetch(url); console.info("status", res.status); return res.status; } catch (e) { console.error(e); return 500; } };
CommonJS module handler
例 – async/await を使用した HTTP リクエスト
const https = require("https"); let url = "https://aws.amazon.com/"; exports.handler = async function (event) { let statusCode; await new Promise(function (resolve, reject) { https.get(url, (res) => { statusCode = res.statusCode; resolve(statusCode); }).on("error", (e) => { reject(Error(e)); }); }); console.log(statusCode); return statusCode; };

次の例では、async/await を使用して Amazon Simple Storage Service バケットを一覧表示します。

注記

この例を使用する前に、関数の実行ロールに Amazon S3 の読み取り許可があることを確認してください。

ES module handler
例 – async/await を使用した AWS SDK v3

この例では、nodejs18.x 以降のランタイムで利用できる「AWS SDK for JavaScript v3」を使用します。

import {S3Client, ListBucketsCommand} from '@aws-sdk/client-s3'; const s3 = new S3Client({region: 'us-east-1'}); export const handler = async(event) => { const data = await s3.send(new ListBucketsCommand({})); return data.Buckets; };
CommonJS module handler
例 – async/await を使用した AWS SDK v3

この例では、nodejs18.x 以降のランタイムで利用できる「AWS SDK for JavaScript v3」を使用します。

const { S3Client, ListBucketsCommand } = require('@aws-sdk/client-s3'); const s3 = new S3Client({ region: 'us-east-1' }); exports.handler = async (event) => { const data = await s3.send(new ListBucketsCommand({})); return data.Buckets; };

コールバックの使用

コールバックを使用する代わりに、async/await を使用して関数ハンドラーを宣言することをお勧めします。いくつかの理由により、async/await の方が適しています。

  • 読みやすさ: async/await コードは、コールバックコードよりも読みやすく理解しやすいです。コールバックコードは、すぐに理解するのが難しくなり、コールバック地獄に陥る可能性があります。

  • デバッグとエラー処理: コールバックベースのコードのデバッグは難しい場合があります。コールスタックを追跡するのが難しくなり、エラーが簡単に隠れてしまう可能性があります。async/await では、try/catch ブロックを使用してエラーを処理できます。

  • 効率: コールバックでは、多くの場合、コードのさまざまな部分を切り替える必要があります。async/await を使用すると、コンテキストスイッチの回数を減らすことができるため、コードがより効率的になります。

ハンドラーでコールバックを使用すると、関数は、イベントループが空になるか、関数がタイムアウトするまで実行を続けます。レスポンスは、すべてのイベントループタスクが完了するまで、呼び出し元に送信されません。関数がタイムアウトした場合は、エラーが返ります。すぐにレスポンスが返るようにランタイムを設定するには、context.callbackWaitsForEmptyEventLoop を false に設定します。

コールバック関数は、Error とレスポンスの 2 つの引数を取ります。応答オブジェクトは、JSON.stringify と互換性がある必要があります。

次の例の関数では、URL をチェックし、ステータスコードを呼び出し元に返します。

ES module handler
例 – callback を使用した HTTP リクエスト
import https from "https"; let url = "https://aws.amazon.com/"; export function handler(event, context, callback) { https.get(url, (res) => { callback(null, res.statusCode); }).on("error", (e) => { callback(Error(e)); }); }
CommonJS module handler
例 – callback を使用した HTTP リクエスト
const https = require("https"); let url = "https://aws.amazon.com/"; exports.handler = function (event, context, callback) { https.get(url, (res) => { callback(null, res.statusCode); }).on("error", (e) => { callback(Error(e)); }); };

次の例では、Amazon S3 のレスポンスは、有効になるとすぐに呼び出し元に返ります。イベントループで実行されているタイムアウトは停止し、次に関数が呼び出されたときに実行を継続します。

注記

この例を使用する前に、関数の実行ロールに Amazon S3 の読み取り許可があることを確認してください。

ES module handler
例 – callbackWaitsForEmptyEventLoop を使用した AWS SDK v3

この例では、nodejs18.x 以降のランタイムで利用できる「AWS SDK for JavaScript v3」を使用します。

import AWS from "@aws-sdk/client-s3"; const s3 = new AWS.S3({}); export const handler = function (event, context, callback) { context.callbackWaitsForEmptyEventLoop = false; s3.listBuckets({}, callback); setTimeout(function () { console.log("Timeout complete."); }, 5000); };
CommonJS module handler
例 – callbackWaitsForEmptyEventLoop を使用した AWS SDK v3

この例では、nodejs18.x 以降のランタイムで利用できる「AWS SDK for JavaScript v3」を使用します。

const AWS = require("@aws-sdk/client-s3"); const s3 = new AWS.S3({}); exports.handler = function (event, context, callback) { context.callbackWaitsForEmptyEventLoop = false; s3.listBuckets({}, callback); setTimeout(function () { console.log("Timeout complete."); }, 5000); };