Node.js の AWS Lambda 関数ハンドラー
Lambda 関数のハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。ハンドラーによってレスポンスが終了するか、レスポンスが返ったら、別のイベントを処理できるようになります。
次の例の関数では、イベントオブジェクトの内容をログに記録して、そのログの場所を返します。
例 index.js
exports.handler = async function(event, context) { console.log("EVENT: \n" + JSON.stringify(event, null, 2)) return context.logStreamName }
関数を設定すると、ハンドラー設定の値はファイル名とエクスポートしたハンドラーメソッドの名前をドットで区切ったものになります。コンソールのデフォルトと、このガイドの例では、index.handler
です。これは、handler
ファイルからエクスポートされた index.js
メソッドを示します。
ランタイムでは、ハンドラーメソッドに 3 つの引数を渡します。最初の引数は、呼び出し元からの情報を含む event
オブジェクトです。呼び出し元は、Invoke を呼び出してこの情報を JSON 形式の文字列として渡し、ランタイムはそれをオブジェクトに変換します。AWS のサービスで関数を呼び出す場合、そのイベント構造はサービスによって異なります。
2 番目の引数は、コンテキストオブジェクトです。この引数には、呼び出し、関数、および実行環境に関する情報が含まれます。前述の例では、関数は、コンテキストオブジェクトからログストリームの名前を取得し、それを呼び出し元に返します。
3 番目の引数 callback
は、レスポンスを送信するために non-async ハンドラーで呼び出すことができる関数です。コールバック関数は、Error
とレスポンスの 2 つの引数を取ります。呼び出すと、Lambda はイベントループが空になるのを待ってから呼び出し元にレスポンスまたはエラーを返します。応答オブジェクトは、JSON.stringify
と互換性がある必要があります。
非同期ハンドラーの場合は、callback
を使用する代わりに、レスポンス、エラー、または promise をランタイムに返します。
関数に追加の依存関係がある場合は、npm を使用してそれらのパッケージをデプロイパッケージに含めます。
非同期ハンドラー
非同期ハンドラーでは、return
および throw
をそれぞれ使用して、レスポンスまたはエラーを送信することができます。これらのメソッドを使用してレスポンスまたはエラーを返すには、関数でキーワード async
を使用する必要があります。
コードで非同期タスクを実行する場合は、実行が終了することを確認できるように promise を返します。promise を解決または拒否した場合、Lambda は、レスポンスまたはエラーを呼び出し元に返します。
例 index.js ファイル - 非同期ハンドラーおよび promise を含む HTTP リクエスト
const https = require('https') let url = "https://docs.aws.amazon.com/lambda/latest/dg/welcome.html" exports.handler =
async
function(event) { const promise = new Promise(function(resolve, reject) { https.get(url, (res) => { resolve(res.statusCode) }).on('error', (e) => { reject(Error(e)) }) }) return promise }
promise を返すライブラリでは、その promise を直接ランタイムに返すことができます。
例 index.js ファイル - 非同期ハンドラーおよび promise を含む AWS SDK
const AWS = require('aws-sdk') const s3 = new AWS.S3() exports.handler = async function(event) { return s3.listBuckets().promise() }
Node.js モジュールと top-level await の使用
関数コードを ES モジュールとして指定することができます。これは、関数ハンドラーの範囲外で、ファイルのトップレベルでの await
の使用を可能にします。これは、ハンドラーの呼び出し前に非同期初期化コードが完了されることを保証し、コールドスタートレイテンシーの削減における Provisioned Concurrency の有効性を最大化します。これは、関数の package.json
ファイルで type
を module
として指定する方法と、.mjs ファイル名拡張子を使用する方法の 2 つの方法で実行できます。
最初のシナリオでは、関数コードがすべての.js ファイルを ES モジュールとして扱い、2 番目のシナリオでは、.mjs で指定したファイルのみが ES モジュールになります。.mjs ファイルは常に ES モジュールであり、.cjs ファイルは常に CommonJS モジュールであることから、ES モジュールと CommonJS モジュールをそれぞれ.mjs と .cjs として命名することで、それらを混在させることができます。
詳細情報とサンプルについては、「Using Node.js ES Modules and Top-Level Await in AWS Lambda
非同期ではないハンドラー
次の例の関数では、URL をチェックし、ステータスコードを呼び出し元に返します。
例 index.js ファイル - コールバックを含む HTTP リクエスト
const https = require('https') let url = "https://docs.aws.amazon.com/lambda/latest/dg/welcome.html" exports.handler = function(event, context, callback) { https.get(url, (res) => {
callback(null, res.statusCode)
}).on('error', (e) => {callback(Error(e))
}) }
非ハンドラーではない関数の場合は、イベントループ
次の例では、Amazon S3 のレスポンスは、有効になるとすぐに呼び出し元に返ります。イベントループで実行されているタイムアウトは停止し、次に関数が呼び出されたときに実行を継続します。
例 index.js ファイル - callbackWaitsForEmptyEventLoop
const AWS = require('aws-sdk') const s3 = new AWS.S3() exports.handler = function(event, context, callback) { context.callbackWaitsForEmptyEventLoop = false s3.listBuckets(null, callback) setTimeout(function () { console.log('Timeout complete.') }, 5000) }