Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Definieren Sie den Lambda-Funktionshandler in TypeScript
Der Lambda-Funktionshandler ist die Methode in Ihrem Funktionscode, die Ereignisse verarbeitet. Wenn Ihre Funktion aufgerufen wird, führt Lambda die Handler-Methode aus. Ihre Funktion wird so lange ausgeführt, bis der Handler eine Antwort zurückgibt, beendet wird oder ein Timeout auftritt.
Auf dieser Seite wird beschrieben, wie Sie mit Lambda-Funktionshandlern arbeiten TypeScript, einschließlich Optionen für die Projekteinrichtung, Benennungskonventionen und Best Practices. Diese Seite enthält auch ein Beispiel für eine TypeScript Lambda-Funktion, die Informationen über eine Bestellung aufnimmt, eine Textdateiquittung erstellt und diese Datei in einem Amazon Simple Storage Service (Amazon S3) -Bucket ablegt. Informationen darüber, wie Sie Ihre Funktion nach dem Schreiben einsetzen können, finden Sie unter Stellen Sie transpilierten TypeScript Code in Lambda mit ZIP-Dateiarchiven bereit oder Stellen Sie transpilierten TypeScript-Code in Lambda mit Container-Images bereit.
Ihr TypeScript Projekt einrichten
Verwenden Sie eine lokale integrierte Entwicklungsumgebung (IDE) oder einen Texteditor, um Ihren TypeScript Funktionscode zu schreiben. Sie können auf der Lambda-Konsole keinen TypeScript Code erstellen.
Es gibt mehrere Möglichkeiten, ein TypeScript Lambda-Projekt zu initialisieren. Sie können beispielsweise ein Projekt mit npm erstellen oder eine AWS SAM - bzw. AWS CDK -Anwendung erstellen. So erstellen Sie das Projekt mit npm:
npm init
Ihr Funktionscode befindet sich in einer .ts Datei, die Sie bei der Erstellung in eine JavaScript Datei transpilieren. Sie können entweder esbuildtsc) von Microsoft verwenden, um Ihren Code in diese Datei zu transpilieren. TypeScript JavaScript Um „esbuild“ zu verwenden, fügen Sie es als Entwicklungsabhängigkeit hinzu:
npm install -D esbuild
Ein typisches TypeScript Lambda-Funktionsprojekt folgt dieser allgemeinen Struktur:
/project-root ├── index.ts - Contains main handler ├── dist/ - Contains compiled JavaScript ├── package.json - Project metadata and dependencies ├── package-lock.json - Dependency lock file ├── tsconfig.json - TypeScript configuration └── node_modules/ - Installed dependencies
Beispiel für einen TypeScript Lambda-Funktionscode
Das folgende Beispiel für einen Lambda-Funktionscode nimmt Informationen über eine Bestellung auf, erstellt eine Textdateiquittung und platziert diese Datei in einem Amazon-S3-Bucket. Dieses Beispiel definiert einen benutzerdefinierten Ereignistyp (OrderEvent). Informationen zum Importieren von Typdefinitionen für AWS Ereignisquellen finden Sie unter Typdefinitionen für Lambda.
Anmerkung
In diesem Beispiel wird ein ES-Modul-Handler verwendet. Lambda unterstützt sowohl ES-Modul- als auch CommonJS-Handler. Weitere Informationen finden Sie unter CommonJS- und ES-Module.
Beispiel Lambda-Funktion „index.ts“
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; // Initialize the S3 client outside the handler for reuse const s3Client = new S3Client(); // Define the shape of the input event type OrderEvent = { order_id: string; amount: number; item: string; } /** * Lambda handler for processing orders and storing receipts in S3. */ export const handler = async (event: OrderEvent): Promise<string> => { try { // Access environment variables const bucketName = process.env.RECEIPT_BUCKET; if (!bucketName) { throw new Error('RECEIPT_BUCKET environment variable is not set'); } // Create the receipt content and key destination const receiptContent = `OrderID: ${event.order_id}\nAmount: $${event.amount.toFixed(2)}\nItem: ${event.item}`; const key = `receipts/${event.order_id}.txt`; // Upload the receipt to S3 await uploadReceiptToS3(bucketName, key, receiptContent); console.log(`Successfully processed order ${event.order_id} and stored receipt in S3 bucket ${bucketName}`); return 'Success'; } catch (error) { console.error(`Failed to process order: ${error instanceof Error ? error.message : 'Unknown error'}`); throw error; } }; /** * Helper function to upload receipt to S3 */ async function uploadReceiptToS3(bucketName: string, key: string, receiptContent: string): Promise<void> { try { const command = new PutObjectCommand({ Bucket: bucketName, Key: key, Body: receiptContent }); await s3Client.send(command); } catch (error) { throw new Error(`Failed to upload receipt to S3: ${error instanceof Error ? error.message : 'Unknown error'}`); } }
Diese index.ts-Datei enthält die folgenden Abschnitte des Codes:
-
import-Block: Verwenden Sie diesen Block, um Bibliotheken einzubinden, die Ihre Lambda-Funktion benötigt, z. B. AWS SDK-Clients. -
const s3Client-Deklaration: Hiermit wird ein Amazon-S3-Client außerhalb der Handler-Funktion initialisiert. Dies veranlasst Lambda, diesen Code während der Initialisierungsphase auszuführen und der Client wird für die Wiederverwendung über mehrere Aufrufe hinweg aufbewahrt. -
type OrderEvent: Definiert die Struktur des erwarteten Eingabeereignisses. -
export const handler: Dies ist die Haupt-Handler-Funktion, die Lambda aufruft. Geben Sie beim Bereitstellen Ihrer Funktionindex.handlerfür die Handler-Eigenschaft an. Der Wert der EigenschaftHandlerbesteht aus dem Dateinamen und dem Namen der exportierten Handler-Methode, getrennt durch einen Punkt. -
uploadReceiptToS3-Funktion: Dies ist eine Hilfsfunktion, auf die von der Haupt-Handler-Funktion verwiesen wird.
Damit diese Funktion ordnungsgemäß funktioniert, muss ihre Ausführungsrolle die s3:PutObject-Aktion zulassen. Stellen Sie außerdem sicher, dass Sie die RECEIPT_BUCKET-Umgebungsvariable definieren. Nach einem erfolgreichen Aufruf sollte der Amazon-S3-Bucket eine Empfangsdatei enthalten.
CommonJS- und ES-Module
Node.js unterstützt zwei Modulsysteme: CommonJS und ECMAScript Module (ES-Module). Lambda empfiehlt die Verwendung von ES-Modulen, da sie Await auf oberster Ebene unterstützen, wodurch asynchrone Aufgaben während der Initialisierung der Ausführungsumgebung abgeschlossen werden können.
Node.js behandelt Dateien mit einer .cjs Dateinamenerweiterung als CommonJS-Module, während eine .mjs Erweiterung ES-Module bezeichnet. Standardmäßig behandelt Node.js Dateien mit der .js Dateinamenerweiterung als CommonJS-Module. Sie können Node.js so konfigurieren, dass .js Dateien als ES-Module behandelt werden, indem Sie das type as module in der package.json Funktionsdatei angeben. Sie können Node.js in Lambda so konfigurieren, dass automatisch erkannt wird, ob eine .js Datei als CommonJS- oder als ES-Modul behandelt werden soll, indem Sie der NODE_OPTIONS Umgebungsvariablen das —experimental-detect-module Flag hinzufügen. Weitere Informationen finden Sie unter Experimentelle Funktionen von Node.js.
Die folgenden Beispiele zeigen Funktionshandler, die sowohl mit ES-Modulen als auch mit CommonJS-Modulen geschrieben wurden. Die übrigen Beispiele auf dieser Seite verwenden alle ES-Module.
Initialisierung von Node.js
Node.js verwendet ein nicht blockierendes I/O Modell, das effiziente asynchrone Operationen mithilfe einer Ereignisschleife unterstützt. Wenn Node.js beispielsweise einen Netzwerkaufruf tätigt, verarbeitet die Funktion weiterhin andere Operationen, ohne eine Netzwerkantwort zu blockieren. Wenn die Netzwerkantwort empfangen wird, wird sie in die Rückrufwarteschlange gestellt. Aufgaben aus der Warteschlange werden verarbeitet, wenn die aktuelle Aufgabe abgeschlossen ist.
Lambda empfiehlt die Verwendung von Await auf oberster Ebene, damit asynchrone Aufgaben, die während der Initialisierung der Ausführungsumgebung initiiert wurden, während der Initialisierung abgeschlossen werden. Asynchrone Aufgaben, die während der Initialisierung nicht abgeschlossen werden, werden normalerweise beim ersten Funktionsaufruf ausgeführt. Dies kann zu unerwartetem Verhalten oder Fehlern führen. Beispielsweise kann Ihre Funktionsinitialisierung einen Netzwerkaufruf ausführen, um einen Parameter aus dem AWS Parameterspeicher abzurufen. Wenn diese Aufgabe während der Initialisierung nicht abgeschlossen wird, kann der Wert während eines Aufrufs Null sein. Es kann auch zu einer Verzögerung zwischen der Initialisierung und dem Aufruf kommen, was bei zeitkritischen Vorgängen zu Fehlern führen kann. Insbesondere AWS Serviceabrufe können sich auf zeitkritische Anforderungssignaturen stützen, was dazu führt, dass Serviceabrufe fehlschlagen, wenn der Anruf während der Initialisierungsphase nicht abgeschlossen wird. Das Abschließen von Aufgaben während der Initialisierung verbessert in der Regel die Kaltstartleistung und die Leistung beim ersten Aufrufen, wenn Provisioned Concurrency verwendet wird. Weitere Informationen finden Sie in unserem Blogbeitrag Using Node.js ES modules and top
Namenskonventionen für Handler
Wenn Sie eine Funktion konfigurieren, besteht der Wert der Handler-Einstellung aus dem Dateinamen und dem Namen der exportierten Handler-Methode, getrennt durch einen Punkt. Der Standardwert für Funktionen, die in der Konsole erstellt werden und für die Beispiele in diesem Handbuch ist index.handler. Dies deutet auf die handler-Methode hin, die aus der index.js- oder index.mjs-Datei wurde.
Wenn Sie eine Funktion in der Konsole mit einem anderen Dateinamen oder Funktionshandlernamen erstellen, müssen Sie den Standardhandlernamen bearbeiten.
So ändern Sie den Funktionshandlernamen (Konsole)
-
Öffnen Sie die Seite Functions (Funktionen)
der Lambda-Konsole und wählen Sie eine Funktion aus. -
Wählen Sie die Registerkarte Code (Code).
-
Scrollen Sie nach unten zum Bereich Laufzeiteinstellungen und wählen Sie Bearbeiten.
-
Geben Sie unter Handler den neuen Namen für Ihren Funktionshandler ein.
-
Wählen Sie Speichern.
Definieren Sie das Eingabeereignisobjekt und greifen Sie darauf zu
JSON ist das gebräuchlichste und standardmäßigste Eingabeformat für Lambda-Funktionen. In diesem Beispiel erwartet die Funktion eine Eingabe ähnlich der folgenden:
{ "order_id": "12345", "amount": 199.99, "item": "Wireless Headphones" }
Wenn Sie mit Lambda-Funktionen in arbeiten TypeScript, können Sie die Form des Eingabeereignisses mithilfe eines Typs oder einer Schnittstelle definieren. In diesem Beispiel definieren wir die Ereignisstruktur mithilfe eines Typs:
type OrderEvent = {
order_id: string;
amount: number;
item: string;
}
Nachdem Sie den Typ oder die Schnittstelle definiert haben, verwenden Sie ihn bzw. sie in der Signatur Ihres Handlers, um die Typsicherheit zu gewährleisten:
export const handler = async (event: OrderEvent): Promise<string> => {
TypeScript Überprüft während der Kompilierung, ob das Ereignisobjekt die erforderlichen Felder mit den richtigen Typen enthält. Der TypeScript Compiler meldet beispielsweise einen Fehler, wenn Sie versuchen, eine Zahl oder event.amount eine Zeichenfolge zu verwendenevent.order_id.
Gültige Handlermuster für Funktionen TypeScript
Wir empfehlen, dass Sie async/await verwenden, um den Funktionshandler zu deklarieren, anstatt Callbacks zu verwenden. Async/await ist eine präzise und lesbare Methode, asynchronen Code zu schreiben, ohne dass verschachtelte Callbacks oder verkettete Zusagen erforderlich sind. Mit Async/Await können Sie Code schreiben, der sich wie synchroner Code liest, aber dennoch asynchron und blockierungsfrei ist.
Für die Beispiele in diesem Abschnitt wird der Typ S3Event verwendet. Sie können jedoch alle anderen AWS Ereignistypen im Paket @types /aws-lambda
-
Fügen Sie das Paket @types/aws-lambda als Entwicklungsabhängigkeit hinzu:
npm install -D @types/aws-lambda -
Importieren Sie die Typen, die Sie benötigen, wie
Context,S3EventoderCallback.
asynchrone Funktionshandler (empfohlen)
Das async-Schlüsselwort kennzeichnet eine Funktion als asynchron, und das await-Schlüsselwort unterbricht die Ausführung der Funktion, bis Promise aufgelöst ist. Der Handler akzeptiert die folgenden Argumente:
-
event: Enthält die an Ihre Funktion übergebenen Eingabedaten. -
context: Enthält Informationen über den Aufruf, die Funktion und die Ausführungsumgebung. Weitere Informationen finden Sie unter Verwenden des Lambda-Kontextobjekts zum Abrufen von TypeScript Funktionsinformationen.
Hier sind die gültigen Signaturen für das async/await Muster:
export const handler = async(event: S3Event): Promise<void> => { };
export const handler = async(event: S3Event, context: Context): Promise<void> => { };
Anmerkung
Bei der asynchronen Verarbeitung von Arrays von Elementen sollten Sie „Await“ mit Promise.all verwenden, um sicherzustellen, dass alle Vorgänge abgeschlossen werden. Methoden wie forEach warten nicht darauf, dass asynchrone Callbacks abgeschlossen werden. Weitere Informationen finden Sie unter Array.prototype.forEach ()
Handler für synchrone Funktionen
Wenn Ihre Funktion keine asynchronen Aufgaben ausführt, können Sie einen synchronen Funktionshandler verwenden, der eine der folgenden Funktionssignaturen verwendet:
export const handler = (event: S3Event): void => { };
export const handler = (event: S3Event, context: Context): void => { };
Handler für Antwort-Streaming-Funktionen
Lambda unterstützt Response-Streaming mit Node.js. Handler für Antwort-Streaming-Funktionen verwenden den Dekorator AWSLambda.streamifyResponse () und verwenden drei Parameter: event, responseStream und context. Die Funktionssignatur lautet:
export const handler = awslambda.streamifyResponse(async (event: APIGatewayProxyEvent, responseStream: NodeJS.WritableStream, context: Context) => { });
Weitere Informationen finden Sie unter Antwortstreaming für Lambda-Funktionen.
Callback-basierte Funktionshandler
Anmerkung
Callback-basierte Funktionshandler werden nur bis zu Node.js 22 unterstützt. Ab Node.js 24 sollten asynchrone Aufgaben mithilfe von asynchronen Funktionshandlern implementiert werden.
Callback-basierte Funktionshandler können die Event-, Kontext- und Callback-Argumente verwenden. Das Callback-Argument erwartet Error und eine Antwort, die JSON-serialisierbar sein muss.
Hier ist die gültige Signatur für das Callback-Handler-Muster:
export const handler =(event: S3Event, context: Context, callback: Callback<void>): void => { };
Die Funktion wird so lange ausgeführt, bis die Ereignisschleife
Beispiel TypeScript Funktion mit Rückruf
Das folgende Beispiel verwendet APIGatewayProxyCallback, einen Callback-Typ, der speziell für API-Gateway-Integrationen gilt. Die meisten AWS Ereignisquellen verwenden den generischen Callback Typ, der in den obigen Signaturen gezeigt wird.
import { Context, APIGatewayProxyCallback, APIGatewayEvent } from 'aws-lambda'; export const lambdaHandler = (event: APIGatewayEvent, context: Context, callback: APIGatewayProxyCallback): void => { console.log(`Event: ${JSON.stringify(event, null, 2)}`); console.log(`Context: ${JSON.stringify(context, null, 2)}`); callback(null, { statusCode: 200, body: JSON.stringify({ message: 'hello world', }), }); };
Verwenden Sie das SDK für JavaScript v3 in Ihrem Handler
Oft verwenden Sie Lambda-Funktionen, um mit anderen AWS Ressourcen zu interagieren oder diese zu aktualisieren. Die einfachste Art, eine Schnittstelle zu diesen Ressourcen herzustellen, ist die Verwendung von AWS SDK für JavaScript. Alle unterstützten Lambda Node.js Runtimes enthalten das SDK für JavaScript Version 3. Wir empfehlen jedoch dringend, dass Sie die benötigten AWS SDK-Clients in Ihr Bereitstellungspaket aufnehmen. Dadurch wird die Abwärtskompatibilität bei zukünftigen Lambda-Laufzeit-Updates maximiert.
Um Ihrer Funktion SDK-Abhängigkeiten hinzuzufügen, verwenden Sie den npm install-Befehl für die spezifischen SDK-Clients, die Sie benötigen. Im Beispielcode haben wir den Amazon-S3-Client verwendet. Fügen Sie diese Abhängigkeit hinzu, indem Sie den folgenden Befehl in dem Verzeichnis ausführen, das Ihre package.json-Datei enthält:
npm install @aws-sdk/client-s3
Importieren Sie im Funktionscode den Client und die Befehle, die Sie benötigen, wie in der Beispielfunktion gezeigt:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
Initialisieren Sie dann einen Amazon-S3-Client:
const s3Client = new S3Client();
In diesem Beispiel haben wir unseren Amazon-S3-Client außerhalb der Haupt-Handler-Funktion initialisiert, um zu vermeiden, dass wir ihn bei jedem Aufruf unserer Funktion initialisieren müssen. Nachdem Sie Ihren SDK-Client initialisiert haben, können Sie ihn verwenden, um API-Aufrufe für diesen AWS Dienst zu tätigen. Der Beispielcode ruft die Amazon S3 PutObjectS3-API-Aktion wie folgt auf:
const command = new PutObjectCommand({
Bucket: bucketName,
Key: key,
Body: receiptContent
});
Zugriff auf Umgebungsvariablen
In Ihrem Handler-Code können Sie mithilfe von process.env auf beliebige Umgebungsvariablen verweisen. In diesem Beispiel verweisen wir mit den folgenden Codezeilen auf die definierte RECEIPT_BUCKET-Umgebungsvariable:
// Access environment variables const bucketName = process.env.RECEIPT_BUCKET; if (!bucketName) { throw new Error('RECEIPT_BUCKET environment variable is not set'); }
Verwenden des globalen Zustands
Lambda führt Ihren statischen Code während der Initialisierungsphase aus, bevor Ihre Funktion zum ersten Mal aufgerufen wird. Ressourcen, die während der Initialisierung erstellt werden, bleiben zwischen Aufrufen im Speicher, sodass Sie sie nicht bei jedem Aufruf Ihrer Funktion neu erstellen müssen.
Im Beispielcode befindet sich der Initialisierungscode des S3-Clients außerhalb des Handlers. Die Laufzeit initialisiert den Client, bevor die Funktion ihr erstes Ereignis ausführt, und der Client bleibt für die Wiederverwendung bei allen Aufrufen verfügbar.
Bewährte Codepraktiken für TypeScript Lambda-Funktionen
Befolgen Sie diese Richtlinien, wenn Sie Lambda-Funktionen erstellen:
-
Trennen Sie den Lambda-Handler von Ihrer Core-Logik. Auf diese Weise können Sie eine Funktion zur besseren Prüfbarkeit von Einheiten schaffen.
-
Kontrollieren Sie die Abhängigkeiten im Bereitstellungspaket Ihrer Funktion. Die AWS Lambda Ausführungsumgebung enthält eine Reihe von Bibliotheken. Für die Laufzeiten Node.js und Python gehören dazu die AWS SDKs. Um die neuesten Funktionen und Sicherheitsupdates zu aktivieren, wird Lambda diese Bibliotheken regelmäßig aktualisieren. Diese Updates können das Verhalten Ihrer Lambda-Funktion geringfügig verändern. Um die Abhängigkeiten, die Ihre Funktion verwendet, vollständig zu kontrollieren, empfehlen wir, alle Abhängigkeiten mit Ihrem Bereitstellungspaket zu bündeln.
-
Minimieren Sie die Komplexität Ihrer Abhängigkeiten. Ziehen Sie einfachere Frameworks vor, die sich schnell beim Start der Ausführungsumgebung laden lassen.
-
Minimieren Sie die Größe Ihres Bereitstellungspakets auf die für die Laufzeit erforderliche Größe. Dadurch verkürzt sich die Zeit, die für das Herunterladen und Entpacken Ihres Bereitstellungspakets vor dem Aufruf benötigt wird.
Nutzen Sie die Wiederverwendung der Ausführungsumgebung zur Verbesserung Ihrer Funktion. Initialisieren Sie SDK-Clients und Datenbankverbindungen außerhalb des Funktions-Handlers und speichern Sie statische Komponenten lokal im /tmp-Verzeichnis. Nachfolgende Aufrufe, die von derselben Instance Ihrer Funktion verarbeitet werden, können diese Ressourcen wiederverwenden. Dies spart Kosten durch Reduzierung der Funktionslaufzeit.
Um potenzielle Datenlecks über Aufrufe hinweg zu vermeiden, verwenden Sie die Ausführungsumgebung nicht, um Benutzerdaten, Ereignisse oder andere Informationen mit Sicherheitsauswirkungen zu speichern. Wenn Ihre Funktion auf einem veränderbaren Zustand beruht, der nicht im Speicher innerhalb des Handlers gespeichert werden kann, sollten Sie für jeden Benutzer eine separate Funktion oder separate Versionen einer Funktion erstellen.
Verwenden Sie eine Keep-Alive-Direktive, um dauerhafte Verbindungen zu pflegen. Lambda bereinigt Leerlaufverbindungen im Laufe der Zeit. Der Versuch, eine Leerlaufverbindung beim Aufruf einer Funktion wiederzuverwenden, führt zu einem Verbindungsfehler. Um Ihre persistente Verbindung aufrechtzuerhalten, verwenden Sie die Keep-Alive-Direktive, die Ihrer Laufzeit zugeordnet ist. Ein Beispiel finden Sie unter Wiederverwenden von Verbindungen mit Keep-Alive in Node.js.
Verwenden Sie Umgebungsvariablen um Betriebsparameter an Ihre Funktion zu übergeben. Wenn Sie z. B. Daten in einen Amazon-S3-Bucket schreiben, anstatt den Bucket-Namen, in den Sie schreiben, hartzucodieren, konfigurieren Sie den Bucket-Namen als Umgebungsvariable.
Vermeiden Sie rekursive Aufrufe in Ihrer Lambda-Funktion, bei denen die Funktion sich selbst aufruft oder einen Prozess initiiert, der die Funktion erneut aufrufen kann. Dies kann zu unvorhergesehenen Mengen an Funktionsaufrufen führen und höhere Kosten zur Folge haben. Wenn Sie eine unbeabsichtigte Menge von Aufrufen feststellen, legen Sie die reservierte gleichzeitige Ausführung der Funktion auf 0 fest, um sofort alle Aufrufe der Funktion zu drosseln, während Sie den Code aktualisieren.
Verwenden Sie APIs in Ihrem Lambda-Funktionscode nicht undokumentiert, nicht öffentlich. Für AWS Lambda verwaltete Laufzeiten führt Lambda regelmäßig Sicherheits- und Funktionsupdates für interne Lambda-Laufzeiten durch. APIs Diese internen API-Updates können abwärtsinkompatibel sein, was zu unbeabsichtigten Folgen wie Aufruffehlern führen kann, wenn Ihre Funktion von diesen nicht öffentlichen Daten abhängig ist. APIs Eine Liste der öffentlich verfügbaren Programme finden Sie in der API-Referenz. APIs
Schreiben Sie idempotenten Code. Das Schreiben idempotenter Code für Ihre Funktionen stellt sicher, dass doppelte Ereignisse auf die gleiche Weise behandelt werden. Ihr Code sollte Ereignisse ordnungsgemäß validieren und doppelte Ereignisse ordnungsgemäß behandeln. Weitere Informationen finden Sie unter Wie mache ich meine Lambda-Funktion idempotent?