El controlador de la función de Lambda es el método del código de la función que procesa eventos. Cuando se invoca una función, Lambda ejecuta el método del controlador. La función se ejecuta hasta que el controlador devuelve una respuesta, se cierra o se agota el tiempo de espera.
Temas
Conceptos básicos del controlador de Typescript
ejemplo Controlador de TypeScript
Esta función de ejemplo registra el contenido del objeto de evento y devuelve la ubicación de los registros. Tenga en cuenta lo siguiente:
-
Antes de utilizar este código en una función de Lambda, debe agregar el paquete @types/aws-lambda
como dependencia de implementación. Este paquete contiene las definiciones de tipos de Lambda. Cuando @types/aws-lambda
se encuentra instalado, la instrucciónimport
(import ... from 'aws-lambda'
) importa las definiciones de tipo. No importa el paquete NPM deaws-lambda
, que es una herramienta de terceros no relacionada. Para obtener más información, consulte aws-lambdaen el repositorio de GitHub DefinitelyTyped. -
El controlador de este ejemplo es un módulo ES y debe designarse como tal en el archivo
package.json
o mediante la extensión de archivo.mjs
. Para obtener más información, consulte Designación de un controlador de funciones como módulo de ES.
import { Handler } from 'aws-lambda';
export const handler: Handler = async (event, context) => {
console.log('EVENT: \n' + JSON.stringify(event, null, 2));
return context.logStreamName;
};
El tiempo de ejecución pasa argumentos al método del controlador. El primer argumento es el objeto event
, que contiene información del invoker. El invocador pasa esta información como una cadena con formato JSON cuando llama a Invoke y el runtime la convierte en un objeto. Cuando un servicio de AWS invoca su función, la estructura del evento varía en función del servicio. Con TypeScript, recomendamos utilizar anotaciones de texto para el objeto de evento. Para obtener más información, consulte Uso de tipos para el objeto event.
El segundo argumento es el objeto context, que incluye información sobre la invocación, la función y el entorno de ejecución. En el ejemplo anterior, la función obtiene el nombre de flujo de registro del objeto context y lo devuelve al invocador.
También puede utilizar un argumento de devolución de llamada, una función a la que puede llamar en los controladores non-async para enviar una respuesta. Le recomendamos que utilice async/await en lugar de devolución de llamadas. Async/await mejora la legibilidad, el manejo de errores y la eficiencia. Para obtener información sobre las diferencias entre async/await y las devoluciones de llamadas, consulte Uso de devolución de llamadas.
Uso de async/await
Si su código realiza una tarea asíncrona, utilice el patrón async/await para asegurarse de que el controlador termina de ejecutarse. Async/await es una forma concisa y legible de escribir código asíncrono en Node.js, sin necesidad de devoluciones de llamadas anidadas ni promesas encadenadas. Con async/await, puedes escribir código que se lea como código sincrónico, sin dejar de ser asíncrono y sin bloqueo.
La palabra clave async
marca una función como asíncrona y la palabra clave await
detiene la ejecución de la función hasta que se resuelva una Promise
.
ejemplo Función de TypeScript: asíncrona
En este ejemplo se utiliza fetch
, que está disponible en el tiempo de ejecución de nodejs18.x
. Tenga en cuenta lo siguiente:
-
Antes de utilizar este código en una función de Lambda, debe agregar el paquete @types/aws-lambda
como dependencia de implementación. Este paquete contiene las definiciones de tipos de Lambda. Cuando @types/aws-lambda
se encuentra instalado, la instrucciónimport
(import ... from 'aws-lambda'
) importa las definiciones de tipo. No importa el paquete NPM deaws-lambda
, que es una herramienta de terceros no relacionada. Para obtener más información, consulte aws-lambdaen el repositorio de GitHub DefinitelyTyped. -
El controlador de este ejemplo es un módulo ES y debe designarse como tal en el archivo
package.json
o mediante la extensión de archivo.mjs
. Para obtener más información, consulte Designación de un controlador de funciones como módulo de ES.
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
const url = 'https://aws.amazon.com/';
export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
// fetch is available with Node.js 18
const res = await fetch(url);
return {
statusCode: res.status,
body: JSON.stringify({
message: await res.text(),
}),
};
} catch (err) {
console.log(err);
return {
statusCode: 500,
body: JSON.stringify({
message: 'some error happened',
}),
};
}
};
Uso de devolución de llamadas
Le recomendamos que utilice async/await para declarar el controlador de funciones en lugar de utilizar devolución de llamadas. Async/await es una mejor opción por diversas razones:
-
Legibilidad: el código async/await es más fácil de leer y entender que el código de devolución de llamada, que puede volverse difícil de seguir con rapidez y provocar un caos de devolución de llamadas.
-
Depuración y gestión de errores: depurar código basado en devoluciones de llamadas puede resultar difícil. La pila de llamadas puede resultar difícil de seguir y los errores se pueden pasar por alto con facilidad. Con async/await, puede utilizar bloques try/catch para gestionar los errores.
-
Eficiencia: las devoluciones de llamadas a menudo requieren cambiar entre diferentes partes del código. Async/await puede reducir la cantidad de cambios de contexto, lo que resulta en un código más eficiente.
Cuando utiliza devoluciones de llamadas en su controlador, la función prosigue con su ejecución hasta que el bucle de eventos
La función de devolución de llamada toma dos argumentos: un Error
y una respuesta. El objeto de respuesta debe ser compatible con JSON.stringify
.
ejemplo Función de TypeScript con devolución de llamada
Esta función de muestra recibe un evento de Amazon API Gateway, registra los objetos de evento y contexto y luego devuelve una respuesta a API Gateway. Tenga en cuenta lo siguiente:
-
Antes de utilizar este código en una función de Lambda, debe agregar el paquete @types/aws-lambda
como dependencia de implementación. Este paquete contiene las definiciones de tipos de Lambda. Cuando @types/aws-lambda
se encuentra instalado, la instrucciónimport
(import ... from 'aws-lambda'
) importa las definiciones de tipo. No importa el paquete NPM deaws-lambda
, que es una herramienta de terceros no relacionada. Para obtener más información, consulte aws-lambdaen el repositorio de GitHub DefinitelyTyped. -
El controlador de este ejemplo es un módulo ES y debe designarse como tal en el archivo
package.json
o mediante la extensión de archivo.mjs
. Para obtener más información, consulte Designación de un controlador de funciones como módulo de ES.
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',
}),
});
};
Uso de tipos para el objeto event
Se recomienda no utilizar el tipo any
Generación de un evento mediante el comando sam local generate-event
-
Genere un evento de proxy de Amazon Simple Storage Service (Amazon S3).
sam local generate-event s3 put >> S3PutEvent.json
-
Utilice la utilidad quicktype
para generar definiciones de tipos a partir del archivo S3putevent.json. npm install -g quicktype quicktype S3PutEvent.json -o S3PutEvent.ts
-
Utilice los tipos generados en el código.
import { S3PutEvent } from './S3PutEvent'; export const lambdaHandler = async (event: S3PutEvent): Promise<void> => { event.Records.map((record) => console.log(record.s3.object.key)); };
Generación de un evento mediante una definición de código abierto del paquete @types/aws-lambda
-
Agregue el paquete @types/aws-lambda
en forma de dependencia de desarrollo. npm install -D @types/aws-lambda
-
Utilice los tipos en el código.
import { S3Event } from "aws-lambda"; export const lambdaHandler = async (event: S3Event): Promise<void> => { event.Records.map((record) => console.log(record.s3.object.key)); };
Prácticas recomendadas de codificación para las funciones de Lambda en Typescript
Siga las directrices de la siguiente lista para utilizar las prácticas recomendadas de codificación al crear sus funciones de Lambda:
-
Separe el controlador de Lambda de la lógica del núcleo. Esto le permite probar las distintas unidades de la función con mayor facilidad. En Node.js, podría tener este aspecto:
exports.myHandler = function(event, context, callback) { var foo = event.foo; var bar = event.bar; var result = MyLambdaFunction (foo, bar); callback(null, result); } function MyLambdaFunction (foo, bar) { // MyLambdaFunction logic here }
-
Controle las dependencias del paquete de implementación de la función. El entorno de ejecución AWS Lambda contiene varias bibliotecas. Para los tiempos de ejecución de Node.js y Python, estos incluyen los SDK de AWS. Para disponer del conjunto más reciente de características y actualizaciones de seguridad, Lambda actualizará periódicamente estas bibliotecas. Estas actualizaciones pueden introducir cambios sutiles en el comportamiento de la función de Lambda. Para disponer de un control total de las dependencias que utiliza la función, empaquete todas las dependencias con el paquete de implementación.
-
Minimice la complejidad de las dependencias. Son preferibles los marcos de trabajo más sencillos, ya que se cargan rápidamente al arrancar el entorno de ejecución.
-
Minimice el tamaño del paquete de implementación de acuerdo con las necesidades de su tiempo de ejecución. Esto reducirá la cantidad de tiempo que tarda el paquete de implementación en descargarse y desempaquetarse antes de la invocación.
-
Reutilice el entorno de ejecución para mejorar el rendimiento de la función. Inicialice los clientes de SDK y las conexiones de base de datos fuera del controlador de funciones y almacene localmente en caché los recursos estáticos en el directorio
/tmp
. Las invocaciones posteriores procesadas por la misma instancia de su función pueden reutilizar estos recursos. Esto ahorra costes al reducir el tiempo de ejecución de la función.Para evitar posibles filtraciones de datos entre las invocaciones, no utilice el entorno de ejecución para almacenar datos de usuario, eventos u otra información con implicaciones de seguridad. Si su función se basa en un estado mutable que no se puede almacenar en la memoria dentro del controlador, considere crear una función independiente o versiones independientes de una función para cada usuario.
-
Utilice una directiva keep-alive para mantener conexiones persistentes. Lambda purga las conexiones inactivas a lo largo del tiempo. Si intenta reutilizar una conexión inactiva al invocar una función, se producirá un error de conexión. Para mantener la conexión persistente, use la directiva keep-alive asociada al tiempo de ejecución. Para ver un ejemplo, consulte Reutilización de conexiones con Keep-Alive en Node.js.
-
Utilice variables de entorno para pasar parámetros operativos a su función. Por ejemplo, si está escribiendo en un bucket de Amazon S3, en lugar de codificar de forma rígida el nombre del bucket, configúrelo como una variable de entorno.
-
Evite utilizar invocaciones recursivas en la función de Lambda, en las que la función se invoca a sí misma o inicia un proceso que puede volver a invocarla. Esto podría producir un volumen no intencionado de invocaciones de la función y costos elevados. Si observa un volumen imprevisto de invocaciones, establezca la simultaneidad reservada de funciones en
0
inmediatamente para limitar todas las invocaciones de la función mientras actualiza el código. -
No utilice API no documentadas y no públicas en el código de la función de Lambda. Para tiempos de ejecución administrados de AWS Lambda, Lambda aplica periódicamente actualizaciones funcionales y de seguridad a las API internas de Lambda. Estas actualizaciones de las API internas pueden ser incompatibles con versiones anteriores, lo que conlleva consecuencias no deseadas, como errores de invocación si su función depende de estas API no públicas. Consulte la referencia de la API para obtener una lista de las API disponibles públicamente.
-
Escriba el código idempotente. Escribir el código idempotente para las funciones garantiza que los eventos duplicados se gestionen de la misma manera. El código debe validar y gestionar correctamente los eventos duplicados. Para obtener más información, consulte ¿Cómo puedo hacer que mi función de Lambda sea idempotente?
.