Guía para desarrolladores de Node.js de Azure Functions
Artículo
Esta guía es una introducción al desarrollo de Azure Functions con JavaScript o TypeScript. En este artículo se supone que ya ha leído la guía para desarrolladores de Azure Functions.
Importante
El contenido de este artículo cambia en función de la elección del modelo de programación de Node.js en el selector de la parte superior de esta página. La versión que elija debe coincidir con la versión del paquete npm @azure/functions que está usando en la aplicación. Si no le aparece ese paquete en package.json, el valor predeterminado es v3. Obtenga más información sobre las diferencias entre v3 y v4 en la guía de migración.
Como desarrollador de Node.js, puede que también le interese uno de los siguientes artículos:
El modelo de programación de Node.js no debe confundirse con el runtime de Azure Functions:
Modelo de programación: define cómo crea el código y es específico de JavaScript y TypeScript.
Runtime: define el comportamiento subyacente de Azure Functions y se comparte en todos los lenguajes.
La versión del modelo de programación está estrictamente vinculada a la versión del paquete npm @azure/functions. Se versiona independientemente del runtime. Tanto el runtime como el modelo de programación usan el número 4 como versión principal más reciente, pero es casualidad.
No puede mezclar los modelos de programación de las versiones 3 y 4 en la misma aplicación de funciones. En cuanto registre una función de la versión 4 en la aplicación, se omiten las funciones de la versión 3 registradas en los archivos function.json.
Versiones compatibles
En la tabla siguiente se muestra cada versión del modelo de programación de Node.js junto con sus versiones compatibles del entorno de ejecución y la Node.js de Azure Functions.
La carpeta de proyecto principal, <project_root>, puede contener los siguientes archivos:
.vscode/: (Opcional) Contiene la configuración almacenada de Visual Studio Code. Para más información, consulte Configuración de Visual Studio Code.
myFirstFunction/function.json: contiene la configuración del desencadenador, las entradas y las salidas de la función. El nombre del directorio determina el nombre de la función.
myFirstFunction/index.js: almacena el código de la función. Para cambiar esta ruta de acceso de archivo predeterminada, consulte Uso de scriptFile.
.funcignore: (Opcional) declara los archivos que no deben publicarse en Azure. Normalmente, este archivo contiene .vscode/ para omitir la configuración del editor, test/ para omitir los casos de prueba y local.settings.json para evitar la publicación de la configuración de la aplicación local.
host.json: contiene las opciones de configuración global que afectan a todas las funciones de una instancia de aplicación de funciones. Este archivo se publica en Azure. No todas las opciones se admiten cuando se ejecuta localmente. Para más información, consulte host.json.
local.settings.json: se usa para almacenar las cadenas de conexión y la configuración de la aplicación cuando la ejecución se realiza a nivel local. Este archivo no se publica en Azure. Para más información, consulte local.settings.file.
package.json: contiene opciones de configuración como una lista de dependencias de paquete, el punto de entrada principal y los scripts.
La estructura de carpetas necesaria para un proyecto de TypeScript se parece al ejemplo siguiente:
La carpeta de proyecto principal, <project_root>, puede contener los siguientes archivos:
.vscode/: (Opcional) Contiene la configuración almacenada de Visual Studio Code. Para más información, consulte Configuración de Visual Studio Code.
dist/: contiene el código JavaScript compilado después de ejecutar una compilación. El nombre de esta carpeta se puede configurar en el archivo "tsconfig.json" y deberá coincidir con la propiedad scriptFile de los archivos "function.json".
myFirstFunction/function.json: contiene la configuración del desencadenador, las entradas y las salidas de la función. El nombre del directorio determina el nombre de la función. Para los proyectos de TypeScript, este archivo deberá contener una propiedad scriptFile que apunte a su JavaScript compilado.
myFirstFunction/index.ts: almacena el código de la función. Para cambiar esta ruta de acceso de archivo predeterminada, consulte Uso de scriptFile.
.funcignore: (Opcional) declara los archivos que no deben publicarse en Azure. Normalmente, este archivo contiene .vscode/ para omitir la configuración del editor, test/ para omitir los casos de prueba y local.settings.json para evitar la publicación de la configuración de la aplicación local.
host.json: contiene las opciones de configuración global que afectan a todas las funciones de una instancia de aplicación de funciones. Este archivo se publica en Azure. No todas las opciones se admiten cuando se ejecuta localmente. Para más información, consulte host.json.
local.settings.json: se usa para almacenar las cadenas de conexión y la configuración de la aplicación cuando la ejecución se realiza a nivel local. Este archivo no se publica en Azure. Para más información, consulte local.settings.file.
package.json: contiene opciones de configuración como una lista de dependencias de paquete, el punto de entrada principal y los scripts.
tsconfig.json: contiene opciones del compilador de TypeScript, como el directorio de salida.
La carpeta de proyecto principal, <project_root>, puede contener los siguientes archivos:
.vscode/: (Opcional) Contiene la configuración almacenada de Visual Studio Code. Para más información, consulte Configuración de Visual Studio Code.
src/functions/: la ubicación predeterminada para todas las funciones y sus desencadenadores y enlaces relacionados.
test/: (opcional) contiene los casos de prueba de la aplicación de funciones.
.funcignore: (Opcional) declara los archivos que no deben publicarse en Azure. Normalmente, este archivo contiene .vscode/ para omitir la configuración del editor, test/ para omitir los casos de prueba y local.settings.json para evitar la publicación de la configuración de la aplicación local.
host.json: contiene las opciones de configuración global que afectan a todas las funciones de una instancia de aplicación de funciones. Este archivo se publica en Azure. No todas las opciones se admiten cuando se ejecuta localmente. Para más información, consulte host.json.
local.settings.json: se usa para almacenar las cadenas de conexión y la configuración de la aplicación cuando la ejecución se realiza a nivel local. Este archivo no se publica en Azure. Para más información, consulte local.settings.file.
package.json: contiene opciones de configuración como una lista de dependencias de paquete, el punto de entrada principal y los scripts.
La estructura de carpetas recomendada para un proyecto de TypeScript es similar al siguiente ejemplo:
La carpeta de proyecto principal, <project_root>, puede contener los siguientes archivos:
.vscode/: (Opcional) Contiene la configuración almacenada de Visual Studio Code. Para más información, consulte Configuración de Visual Studio Code.
dist/: contiene el código JavaScript compilado después de ejecutar una compilación. El nombre de esta carpeta se puede configurar en el archivo "tsconfig.json".
src/functions/: la ubicación predeterminada para todas las funciones y sus desencadenadores y enlaces relacionados.
test/: (opcional) contiene los casos de prueba de la aplicación de funciones.
.funcignore: (Opcional) declara los archivos que no deben publicarse en Azure. Normalmente, este archivo contiene .vscode/ para omitir la configuración del editor, test/ para omitir los casos de prueba y local.settings.json para evitar la publicación de la configuración de la aplicación local.
host.json: contiene las opciones de configuración global que afectan a todas las funciones de una instancia de aplicación de funciones. Este archivo se publica en Azure. No todas las opciones se admiten cuando se ejecuta localmente. Para más información, consulte host.json.
local.settings.json: se usa para almacenar las cadenas de conexión y la configuración de la aplicación cuando la ejecución se realiza a nivel local. Este archivo no se publica en Azure. Para más información, consulte local.settings.file.
package.json: contiene opciones de configuración como una lista de dependencias de paquete, el punto de entrada principal y los scripts.
tsconfig.json: contiene opciones del compilador de TypeScript, como el directorio de salida.
Registro de una función
El modelo v3 registra una función según la existencia de dos archivos. En primer lugar, necesita un archivo function.json ubicado en una carpeta un nivel por debajo de la raíz de la aplicación. En segundo lugar, necesitará un archivo JavaScript que exporte la función. De forma predeterminada, el modelo busca un archivo index.js en la misma carpeta que function.json. Si usa TypeScript, deberá usar la propiedad scriptFile en function.json para que apunte al archivo JavaScript compilado. Para personalizar la ubicación del archivo o el nombre de exportación de la función, consulte la configuración del punto de entrada de la función.
La función que exporta siempre debe declararse como async function en el modelo v3. Puede exportar una función sincrónica, pero debe llamar a context.done() para indicar que la función se ha completado, lo que está en desuso y no se recomienda.
La función recibe una invocación context como primer argumento y las entradas como argumentos restantes.
El ejemplo siguiente es una función simple que registra que se ha desencadenado y responde con Hello, world!:
El modelo de programación carga las funciones en función del campo main de package.json. Puede establecer el campo main en un único archivo o en varios archivos mediante un patrón global. La siguiente tabla muestra valores de ejemplo para el campo main:
Combinación en la que se registra cada función desde su propio archivo, pero todavía tiene un archivo raíz para el código general de nivel de aplicación.
Ejemplo
Descripción
dist/src/index.js
Registrar funciones desde un único archivo raíz.
dist/src/functions/*.js
Registre cada función desde su propio archivo.
dist/src/{index.js,functions/*.js}
Combinación en la que se registra cada función desde su propio archivo, pero todavía tiene un archivo raíz para el código general de nivel de aplicación.
Para registrar una función, debe importar el objeto app desde el módulo npm @azure/functions y llamar al método específico del tipo de desencadenador. El primer argumento al registrar una función es el nombre de la función. El segundo argumento es un objeto options que especifica la configuración del desencadenador, el controlador y cualquier otra entrada o salida. En algunos casos en los que la configuración del desencadenador no sea necesaria, puede pasar el controlador directamente como segundo argumento en lugar de un objeto options.
El registro de una función se puede realizar desde cualquier archivo del proyecto, siempre y cuando ese archivo se cargue (directa o indirectamente) en función del campo main del archivo package.json. La función debe registrarse en un ámbito global porque no se pueden registrar funciones una vez iniciadas las ejecuciones.
El ejemplo siguiente es una función simple que registra que se ha desencadenado y responde con Hello, world!:
La función es necesaria para tener exactamente una entrada principal denominada desencadenador. También puede tener entradas o salidas secundarias. Las entradas y salidas se configuran en los archivos function.json y también se conocen como enlaces.
Entradas
Las entradas son enlaces con direction establecido en in. La principal diferencia entre un desencadenador y una entrada secundaria es que type para un desencadenador finaliza en Trigger; por ejemplo, el tipo blobTrigger en comparación con el tipo blob. La mayoría de las funciones solo usan un desencadenador y no se admiten muchos tipos de entrada secundarios.
Se puede acceder a las entradas de varias maneras:
[Recomendado] Como argumentos pasados a la función: use los argumentos en el mismo orden en que se definen en function.json. La propiedad name definida en function.json no tiene que coincidir con el nombre del argumento, aunque se recomienda para la organización.
Las salidas son enlaces con direction establecido en out y se pueden establecer de varias maneras:
[Recomendado para una salida única] Devuelva el valor directamente: si usa una función asincrónica, puede devolver el valor directamente. Debe cambiar la propiedad name del enlace de salida a $return en function.json como en el ejemplo siguiente:
[Recomendado para varias salidas] Devuelva un objeto que contenga todas las salidas: si usa una función asincrónica, puede devolver un objeto con una propiedad que coincida con el nombre de cada enlace de function.json. En el ejemplo siguiente se usan enlaces de salida denominados "httpResponse" y "queueOutput":
Establezca valores en context.bindings: si no usa una función asincrónica o no quiere usar las opciones anteriores, puede establecer los valores directamente en context.bindings, en los que la clave coincide con el nombre del enlace. En el ejemplo siguiente se usan enlaces de salida denominados "httpResponse" y "queueOutput":
Puede usar la propiedad dataType en un enlace de entrada para cambiar el tipo de entrada, pero con algunas limitaciones:
En Node.js, solo se admiten string y binary (stream no).
En el caso de las entradas HTTP, se omite la propiedad dataType. En su lugar, use propiedades en el objeto request para obtener el cuerpo en el formato que quiera. Para obtener más información, consulte Solicitud HTTP.
En el ejemplo siguiente de un desencadenador de cola de almacenamiento, el tipo predeterminado de myQueueItem es string, pero si se establece dataType en binary, el tipo cambia a Buffer de Node.js.
const { Buffer } = require('node:buffer');
module.exports = asyncfunction (context, myQueueItem) {
if (typeof myQueueItem === 'string') {
context.log('myQueueItem is a string');
} elseif (Buffer.isBuffer(myQueueItem)) {
context.log('myQueueItem is a buffer');
}
};
TypeScript
import { AzureFunction, Context } from"@azure/functions";
import { Buffer } from'node:buffer';
const queueTrigger1: AzureFunction = asyncfunction (context: Context, myQueueItem: string | Buffer): Promise<void> {
if (typeof myQueueItem === 'string') {
context.log('myQueueItem is a string');
} elseif (Buffer.isBuffer(myQueueItem)) {
context.log('myQueueItem is a buffer');
}
};
exportdefault queueTrigger1;
La función es necesaria para tener exactamente una entrada principal denominada desencadenador. También puede tener entradas secundarias, una salida principal denominada salida de retorno o salidas secundarias. Las entradas y salidas también se conocen como enlaces fuera del contexto del modelo de programación de Node.js. Antes de la versión v4 del modelo, estos enlaces se configuraron en archivos function.json.
Entrada del desencadenador
El desencadenador es la única entrada o salida necesaria. Para la mayoría de los tipos de desencadenador, se registra una función mediante un método en el objeto app denominado después del tipo de desencadenador. Puede especificar la configuración específica del desencadenador directamente en el argumento options. Por ejemplo, un desencadenador HTTP permite especificar una ruta. Durante la ejecución, el valor correspondiente a este desencadenador se pasa como primer argumento al controlador.
La salida de devolución es opcional y, en algunos casos, está configurada de forma predeterminada. Por ejemplo, un desencadenador HTTP registrado con app.http está configurado para devolver automáticamente una salida de respuesta HTTP. Para la mayoría de los tipos de salida, especifique la configuración de devolución en el argumento options con la ayuda del objeto output exportado desde el módulo @azure/functions. Durante la ejecución, esta salida se establece devolviendo desde el controlador.
Además del desencadenador y la devolución, es posible especificar entradas o salidas adicionales en el argumento options al registrar una función. Los objetos input y output exportados desde el módulo @azure/functions proporcionan métodos específicos del tipo para ayudar a construir la configuración. Durante la ejecución, obtiene o establece los valores con context.extraInputs.get o context.extraOutputs.set, pasando el objeto de configuración original como primer argumento.
Los objetos app, trigger, input y output exportados por el módulo @azure/functions proporcionan métodos específicos del tipo para la mayoría de los tipos. Para todos los tipos que no se admiten, se proporciona un método generic para que pueda especificar manualmente la configuración. El método generic también se puede usar si desea cambiar la configuración predeterminada proporcionada por un método específico del tipo.
El ejemplo siguiente es una función simple desencadenada por HTTP mediante métodos genéricos en lugar de métodos específicos del tipo.
Cada invocación de la función recibe un objeto de invocación context, que se usa para leer entradas, establecer salidas, escribir en registros y leer varios metadatos. En el modelo v3, el objeto de contexto siempre es el primer argumento pasado al controlador.
El objeto context tiene las siguientes propiedades:
Propiedad
Descripción
invocationId
El identificador de la invocación de la función actual.
Metadatos sobre la entrada del desencadenador para esta invocación, sin incluir el propio valor. Por ejemplo, un desencadenador del centro de eventos tiene una propiedad enqueuedTimeUtc.
traceContext
Contexto para el seguimiento distribuido. Para obtener más información, vea Trace Context.
bindingDefinitions
Configuración de las entradas y salidas, tal como se define en function.json.
Este método context.done está en desuso. Antes de que se admitieran las funciones asincrónicas, se indicaba que la función había terminado mediante una llamada a context.done():
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
TypeScript
import { AzureFunction, Context, HttpRequest } from"@azure/functions";
const httpTrigger: AzureFunction = function (context: Context, request: HttpRequest): void{
context.log("this pattern is now deprecated");
context.done();
};
exportdefault httpTrigger;
Ahora, se recomienda quitar la llamada a context.done() y marcar la función como asincrónica para que devuelva una promesa (incluso si no aplica await a nada). Tan pronto como finalice la función (en otras palabras, se resuelva la promesa devuelta), el modelo v3 sabrá que la función ha terminado.
module.exports = asyncfunction (context, request) {
context.log("you don't need context.done or an awaited call")
};
TypeScript
import { AzureFunction, Context, HttpRequest } from"@azure/functions";
const httpTrigger: AzureFunction = asyncfunction (context: Context, request: HttpRequest): Promise<void> {
context.log("you don't need context.done or an awaited call")
};
exportdefault httpTrigger;
Cada invocación de la función recibe un objeto context de invocación, con información adicional sobre el contexto y los métodos usados para el registro. En el modelo v4, el objeto context suele ser el segundo argumento pasado al controlador.
La clase InvocationContext tiene las siguientes propiedades:
Propiedad
Descripción
invocationId
El identificador de la invocación de la función actual.
functionName
El nombre de la función.
extraInputs
Se usa para obtener los valores de entradas adicionales. Para obtener más información, consulte Entradas y salidas adicionales.
extraOutputs
Se usa para establecer los valores de salidas adicionales. Para obtener más información, consulte Entradas y salidas adicionales.
Contexto para el seguimiento distribuido. Para obtener más información, vea Trace Context.
triggerMetadata
Metadatos sobre la entrada del desencadenador para esta invocación, sin incluir el propio valor. Por ejemplo, un desencadenador del centro de eventos tiene una propiedad enqueuedTimeUtc.
options
Las opciones usadas al registrar la función, después de que se hayan validado y con los valores predeterminados especificados explícitamente.
Contexto de reintento
El objeto retryContext tiene las siguientes propiedades:
Propiedad
Descripción
retryCount
Número que representa el intento de reintento actual.
maxRetryCount
Número máximo de veces que se reintenta una ejecución. Un valor de -1 significa que se reintentará indefinidamente.
En Azure Functions, se recomienda usar context.log() para escribir registros. Azure Functions se integra con Azure Application Insights para capturar mejor los registros de la aplicación de funciones. Application Insights, que forma parte de Azure Monitor, proporciona funciones para la recopilación, la representación visual y el análisis de los datos de registro de la aplicación y de las salidas del seguimiento. Para más información, consulte Supervisión de Azure Functions.
Nota
Si usa el método alternativo console.log de Node.js, se realiza un seguimiento de esos registros en el nivel de aplicación y no se asociará a ninguna función específica. Se recomienda encarecidamente usar context para el registro, en lugar de console, para que todos los registros estén asociados a una función específica.
En el ejemplo siguiente se escribe un registro en el nivel de "información" predeterminado, incluido el id. de invocación:
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
TypeScript
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
Niveles de registro
Además del método context.log predeterminado, están disponibles los siguientes métodos para permitirle escribir registros en niveles específicos:
Método
Descripción
context.log.error()
Escribe un evento de nivel de error en los registros.
context.log.warn()
Escribe un evento de nivel de advertencia en los registros.
context.log.info()
Escribe un evento de nivel de información en los registros.
context.log.verbose()
Escribe un evento de nivel de seguimiento en los registros.
Método
Descripción
context.trace()
Escribe un evento de nivel de seguimiento en los registros.
context.debug()
Escribe un evento de nivel de depuración en los registros.
context.info()
Escribe un evento de nivel de información en los registros.
context.warn()
Escribe un evento de nivel de advertencia en los registros.
context.error()
Escribe un evento de nivel de error en los registros.
Configurar el nivel de registro
Azure Functions permite definir el nivel de umbral que se usará al seguir y visualizar los registros. Para establecer el umbral, use la propiedad logging.logLevel del archivo host.json. Esta propiedad permite definir un nivel predeterminado aplicado a todas las funciones o un umbral para cada función individual. Para más información, consulte Configuración de la supervisión para Azure Functions.
Seguimiento de datos personalizados
De forma predeterminada, Azure Functions escribe las salidas como seguimientos en Application Insights. Para obtener más control, puede usar en su lugar el SDK de Node.js para Application Insights para enviar los datos personalizados a la instancia de Application Insights.
const appInsights = require("applicationinsights");
appInsights.setup();
const client = appInsights.defaultClient;
module.exports = asyncfunction (context, request) {
// Use this with 'tagOverrides' to correlate custom logs to the parent function invocation.var operationIdOverride = {"ai.operation.id":context.traceContext.traceparent};
client.trackEvent({name: "my custom event", tagOverrides:operationIdOverride, properties: {customProperty2: "custom property value"}});
client.trackException({exception: newError("handled exceptions can be logged with this method"), tagOverrides:operationIdOverride});
client.trackMetric({name: "custom metric", value: 3, tagOverrides:operationIdOverride});
client.trackTrace({message: "trace message", tagOverrides:operationIdOverride});
client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:231, resultCode:0, success: true, dependencyTypeName: "ZSQL", tagOverrides:operationIdOverride});
client.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true, tagOverrides:operationIdOverride});
};
TypeScript
import { AzureFunction, Context, HttpRequest } from"@azure/functions";
import * as appInsights from'applicationinsights';
appInsights.setup();
const client = appInsights.defaultClient;
const httpTrigger: AzureFunction = asyncfunction (context: Context, request: HttpRequest): Promise<void> {
// Use this with 'tagOverrides' to correlate custom logs to the parent function invocation.var operationIdOverride = {"ai.operation.id":context.traceContext.traceparent};
client.trackEvent({name: "my custom event", tagOverrides:operationIdOverride, properties: {customProperty2: "custom property value"}});
client.trackException({exception: newError("handled exceptions can be logged with this method"), tagOverrides:operationIdOverride});
client.trackMetric({name: "custom metric", value: 3, tagOverrides:operationIdOverride});
client.trackTrace({message: "trace message", tagOverrides:operationIdOverride});
client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:231, resultCode:0, success: true, dependencyTypeName: "ZSQL", tagOverrides:operationIdOverride});
client.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true, tagOverrides:operationIdOverride});
};
exportdefault httpTrigger;
El parámetro tagOverrides establece operation_Id en el identificador de invocación de la función. Esta configuración le permite correlacionar todos los registros personalizados y generados automáticamente para una determinada invocación de función.
Desencadenadores HTTP
Los desencadenadores HTTP y de webhook usan objetos de solicitud y respuesta para representar mensajes HTTP.
Los desencadenadores HTTP y de webhook usan objetos HttpRequest y HttpResponse para representar mensajes HTTP. Las clases representan un subconjunto del estándar de captura, mediante el paquete undici de Node.js.
Solicitud HTTP
Se puede acceder a una solicitud de varias maneras:
module.exports = asyncfunction (context, request) {
context.log(`Http function processed request for url "${context.req.url}"`);
TypeScript
const httpTrigger: AzureFunction = asyncfunction (context: Context, request: HttpRequest): Promise<void> {
context.log(`Http function processed request for url "${context.req.url}"`);
Desde los enlaces de entrada con nombre: esta opción funciona igual que cualquier enlace no HTTP. El nombre del enlace de function.json debe coincidir con la clave en context.bindings, o "request1" en el ejemplo siguiente:
module.exports = asyncfunction (context, request) {
context.log(`Http function processed request for url "${context.bindings.request1.url}"`);
TypeScript
const httpTrigger: AzureFunction = asyncfunction (context: Context, request: HttpRequest): Promise<void> {
context.log(`Http function processed request for url "${context.bindings.request1.url}"`);
El objeto HttpRequest tiene las siguientes propiedades:
Propiedad
Tipo
Descripción
method
string
Método de solicitud HTTP usado para invocar esta función.
url
string
URL de la solicitud.
headers
Record<string, string>
Encabezados de solicitud HTTP. Este objeto distingue entre mayúsculas y minúsculas. Se recomienda usar request.getHeader('header-name') en su lugar, que no distingue entre mayúsculas y minúsculas.
query
Record<string, string>
Claves y valores de los parámetros de la cadena de consulta de la URL.
params
Record<string, string>
Valores y claves de parámetros de ruta.
user
HttpRequestUser | null
Objeto que representa al usuario que ha iniciado sesión, ya sea a través de la autenticación de Functions, la autenticación SWA o null cuando no se inicia sesión ningún usuario de este tipo.
body
Buffer | string | any
Si el tipo de medio es "application/octet-stream" o "multipart/*", body es un búfer. Si el valor es una cadena que puede analizar como JSON, body es el objeto analizado. De lo contrario, body es una cadena.
rawBody
string
Cuerpo como cadena. A pesar del nombre, esta propiedad no devuelve un búfer.
bufferBody
Buffer
Cuerpo como búfer.
Se puede acceder a la solicitud como primer argumento para el controlador de una función desencadenada por HTTP.
Claves y valores de los parámetros de la cadena de consulta de la URL.
params
Record<string, string>
Valores y claves de parámetros de ruta.
user
HttpRequestUser | null
Objeto que representa al usuario que ha iniciado sesión, ya sea a través de la autenticación de Functions, la autenticación SWA o null cuando no se inicia sesión ningún usuario de este tipo.
Devuelva la respuesta: si la función es asincrónica y establece el nombre de enlace en $return en function.json, puede devolver la respuesta directamente en lugar de establecerla en context.
Establezca el enlace de entrada con nombre: esta opción funciona igual que cualquier enlace no HTTP. El nombre del enlace de function.json debe coincidir con la clave en context.bindings, o "response1" en el ejemplo siguiente:
Si crea un objeto nuevo al establecer la respuesta, dicho objeto debe coincidir con la interfaz HttpResponseSimple, que tiene las siguientes propiedades:
Propiedad
Tipo
Descripción
headers
Record<string, string> (opcional)
Encabezados de respuesta HTTP.
cookies
Cookie[] (opcional)
Cookies de respuesta HTTP.
body
any (opcional)
Cuerpo de respuesta HTTP.
statusCode
number (opcional)
Código de estado de respuesta HTTP. Si no se establece, el valor predeterminado es 200.
status
number (opcional)
Es igual que statusCode. Esta propiedad se ignora si statusCode está establecido.
También puede modificar el objeto context.res sin sobrescribirlo. El objeto predeterminado context.res usa la interfaz HttpResponseFull, que admite los métodos siguientes además de las propiedades HttpResponseSimple:
Método
Descripción
status()
Establece el estado.
setHeader()
Establece un campo de encabezado. NOTA: res.set() y res.header() también se admiten y hacen lo mismo.
getHeader()
Obtiene un campo de encabezado. NOTA: res.get() también se admite y hace lo mismo.
removeHeader()
Quita un encabezado.
type()
Establece el encabezado "content-type".
send()
Este método es desusado. Establece el cuerpo y llama a context.done() para indicar que ha terminado una función sincrónica. NOTA: res.end() también se admite y hace lo mismo.
sendStatus()
Este método es desusado. Establece el código de estado y llama a context.done() para indicar que ha terminado una función sincrónica.
json()
Este método es desusado. Establece el "content-type" en "application/json", establece el cuerpo y llama a context.done() para indicar que ha terminado una función sincrónica.
La respuesta se puede establecer de varias maneras:
Como interfaz sencilla con el tipo HttpResponseInit: esta opción es la forma más concisa de devolver respuestas.
Como clase con tipo HttpResponse: esta opción proporciona métodos auxiliares para leer y modificar varias partes de la respuesta, como los encabezados.
Valor booleano que indica si el cuerpo ya se ha leído.
Flujos HTTP
Los flujos HTTP son una característica que facilita el procesamiento de datos grandes, transmitir respuestas de OpenAI, ofrecer contenido dinámico y admitir otros escenarios HTTP principales. Permite transmitir solicitudes y respuestas desde puntos de conexión HTTP en la aplicación de funciones de Node.js. Use flujos HTTP en escenarios en los que la aplicación requiera intercambio en tiempo real e interacción entre el cliente y el servidor a través de HTTP. También puede usar secuencias HTTP para obtener el mejor rendimiento y confiabilidad para las aplicaciones cuando se usa HTTP.
Importante
Las secuencias HTTP no se admiten en el modelo v3. Actualice al modelo v4 para usar la característica de streaming HTTP.
Los tipos HttpRequest y HttpResponse existentes del modelo de programación v4 ya admiten varias formas de controlar el cuerpo del mensaje, incluso como una secuencia.
Azure Functions Core Tools versión 4.0.5530 o una versión posterior, que contiene la versión en tiempo de ejecución correcta.
Habilitación de secuencias
Siga estos pasos para habilitar flujos HTTP en la aplicación de funciones en Azure y en los proyectos locales:
Si planea transmitir grandes cantidades de datos, modifique la configuración FUNCTIONS_REQUEST_BODY_SIZE_LIMIT en Azure. El tamaño máximo de cuerpo predeterminado permitido es 104857600, que limita las solicitudes a un tamaño de ~100 MB.
En este ejemplo se muestra una función desencadenada por HTTP que recibe datos a través de una solicitud HTTP POST y la función transmite estos datos a un archivo de salida especificado:
En este ejemplo se muestra una función desencadenada por HTTP que transmite el contenido de un archivo como respuesta a las solicitudes HTTP GET entrantes:
Para obtener una aplicación de ejemplo lista para ejecutar mediante secuencias, consulte este ejemplo en GitHub.
Consideraciones sobre secuencias
Use request.body para obtener la ventaja máxima del uso de secuencias. Todavía puede seguir usando métodos como request.text(), que siempre devuelven el cuerpo como una cadena.
Use un enlace para ejecutar código en distintos puntos del ciclo de vida de Azure Functions. Los enlaces se ejecutan en el orden en que están registrados y se pueden registrar desde cualquier archivo de la aplicación. Actualmente hay dos ámbitos de enlaces, nivel "aplicación" e "invocación".
Enlaces de invocación
Los enlaces de invocación se ejecutan una vez por cada invocación de su función, ya sea antes en un enlace preInvocation o después en un enlace postInvocation. De manera predeterminada, su enlace se ejecuta para todos los tipos de desencadenador, pero también puede filtrar por tipo. En el ejemplo siguiente se muestra cómo registrar un enlace de invocación y filtrar por tipo de desencadenador:
Lugar recomendado para almacenar y compartir datos entre enlaces en el mismo ámbito. Debe usar un nombre de propiedad único para que no entre en conflicto con los datos de otros enlaces.
El objeto PostInvocationContext tiene las siguientes propiedades:
Propiedad
Descripción
inputs
Argumentos pasados a la invocación.
result
Resultado de la función. Los cambios en este valor afectan al resultado general de la función.
error
Error lanzado por la función, o null/indefinido si no hay error. Los cambios en este valor afectan al resultado general de la función.
Lugar recomendado para almacenar y compartir datos entre enlaces en el mismo ámbito. Debe usar un nombre de propiedad único para que no entre en conflicto con los datos de otros enlaces.
Enlaces de aplicación
Los enlaces de aplicación se ejecutan una vez por cada instancia de su aplicación, ya sea durante el inicio en un enlace de appStart o durante la finalización en un enlace de appTerminate. Los enlaces de finalización de aplicación tienen un tiempo limitado para ejecutarse y no se ejecutan en todos los escenarios.
El entorno de ejecución de Azure Functions actualmente no admite registro de contexto fuera de una invocación. Use el paquete npm de Application Insights para registrar los datos durante los enlaces a nivel de aplicación.
En el ejemplo siguiente se registran enlaces de aplicación:
const { app } = require('@azure/functions');
app.hook.appStart((context) => {
// add your logic here
});
app.hook.appTerminate((context) => {
// add your logic here
});
TypeScript
import { app, AppStartContext, AppTerminateContext } from'@azure/functions';
app.hook.appStart((context: AppStartContext) => {
// add your logic here
});
app.hook.appTerminate((context: AppTerminateContext) => {
// add your logic here
});
El primer argumento para el controlador de enlace es un objeto de contexto específico de ese tipo de enlace.
El objeto AppStartContext tiene las siguientes propiedades:
Propiedad
Descripción
hookData
Lugar recomendado para almacenar y compartir datos entre enlaces en el mismo ámbito. Debe usar un nombre de propiedad único para que no entre en conflicto con los datos de otros enlaces.
El objeto AppTerminateContext tiene las siguientes propiedades:
Propiedad
Descripción
hookData
Lugar recomendado para almacenar y compartir datos entre enlaces en el mismo ámbito. Debe usar un nombre de propiedad único para que no entre en conflicto con los datos de otros enlaces.
Escalado y simultaneidad
De forma predeterminada, Azure Functions supervisa automáticamente la carga de su aplicación y crea más instancias de host para Node.js según sea necesario. Azure Functions usa umbrales integrados (no configurables por el usuario) en diferentes tipos de desencadenadores para decidir cuándo se deberán agregar instancias, como la antigüedad de los mensajes y el tamaño de la cola de QueueTrigger. Para obtener más información, consulte Cómo funcionan los planes de consumo y Premium.
Este comportamiento de escalado es suficiente para muchas aplicaciones de Node.js. En las aplicaciones dependientes de la CPU, puede mejorar aún más el rendimiento mediante el uso de varios procesos de trabajo de lenguaje. Puede aumentar el número de procesos de trabajo por host del valor predeterminado de 1 a un máximo de 10 mediante la configuración de la aplicación FUNCTIONS_WORKER_PROCESS_COUNT. Al hacerlo, Azure Functions intenta distribuir uniformemente las invocaciones de función simultáneas en estos trabajos. Este comportamiento hará que sea menos probable que una función que consuma mucha CPU bloquee la ejecución de otras funciones. La configuración se aplica a cada host que Azure Functions crea al escalar horizontalmente la aplicación para satisfacer la demanda.
Advertencia
Use la configuración FUNCTIONS_WORKER_PROCESS_COUNT con precaución. Ejecutar varios procesos en la misma instancia puede provocar un comportamiento impredecible y aumentar los tiempos de carga de la función. Si usa esta configuración, se recomienda encarecidamente compensar estas desventajas mediante la ejecución desde un archivo de paquete.
Versión de Node
Puede ver la versión actual que el entorno de tiempo de ejecución usa mediante el registro de process.version desde cualquier función. Consulte supported versions para obtener una lista de Node.js versiones compatibles con cada modelo de programación.
Especificación de la versión de Node
La forma en que actualice la versión de Node.js depende del sistema operativo en el que se ejecuta la aplicación de funciones.
Cuando se ejecuta en Windows, la versión de Node.js se establece mediante la configuración de la aplicación WEBSITE_NODE_DEFAULT_VERSION. Esta configuración se puede actualizar mediante la CLI de Azure o en el Azure Portal.
Cuando se ejecuta en Linux, la configuración del sitio de linuxfxversion establece la versión de Node.js. Esta configuración se puede actualizar mediante la CLI de Azure.
Ejecute el comando az functionapp config appsettings set de la CLI de Azure para actualizar su versión de Node.js de la aplicación de funciones que se ejecuta en Windows:
Azure CLI
az functionapp config appsettings set --settings WEBSITE_NODE_DEFAULT_VERSION=~20 \
--name<FUNCTION_APP_NAME>--resource-group<RESOURCE_GROUP_NAME>
Siga estos pasos para cambiar la versión de Node.js:
En Azure Portal, busque la aplicación de funciones y seleccione Configuración>Configuración en el lado izquierdo.
Seleccione la pestaña Configuración de los parámetros de ejecución de la función y compruebe que la aplicación de funciones se está ejecutando en la versión más reciente del entorno de ejecución de Functions.
Seleccione la pestaña Configuración general y actualice la versión de Node.js a la versión más reciente. Lo ideal es que ya haya comprobado localmente que las funciones se ejecutan en la versión que seleccione.
Cuando se le notifique sobre un reinicio, seleccione Continuar y luego seleccione Guardar.
Ejecute el comando az functionapp config set de la CLI de Azure para actualizar su versión de Node.js de la aplicación de funciones que se ejecuta en Linux:
Azure CLI
az functionapp config set --linux-fx-version"node|20"--name"<FUNCTION_APP_NAME>" \
--resource-group"<RESOURCE_GROUP_NAME>"
Esto establece la imagen base de la aplicación de funciones de Linux en Node.js versión 20.
Nota
No se puede cambiar la versión de Node.js en el Azure Portal cuando la aplicación de funciones se ejecuta en Linux en un plan de consumo. En su lugar, use la CLI de Azure.
Para los planes Premium y Dedicado, siga estos pasos para cambiar la versión de Node.js:
En Azure Portal, busque la aplicación de funciones y seleccione Configuración>Configuración en el lado izquierdo.
Seleccione la pestaña Configuración de los parámetros de ejecución de la función y compruebe que la aplicación de funciones se está ejecutando en la versión más reciente del entorno de ejecución de Functions.
Seleccione la pestaña Configuración general y actualice la versión de Node.js a la versión más reciente. Lo ideal es que ya haya comprobado localmente que las funciones se ejecutan en la versión que seleccione.
Cuando se le notifique sobre un reinicio, seleccione Continuar y luego seleccione Guardar.
Una vez realizados los cambios, la aplicación de funciones se reinicia. Para saber más sobre la compatibilidad de Node.js con Functions, consulte Directiva de compatibilidad de Language Runtime.
Variables de entorno
Las variables de entorno pueden ser útiles para los secretos operativos (cadenas de conexión, claves, puntos de conexión, etc.) o para la configuración del entorno, como las variables de generación de perfiles. Puede agregar variables de entorno en los entornos locales y en la nube y acceder a ellas a través de process.env en el código de la función.
En el ejemplo siguiente se registra la variable de entorno WEBSITE_SITE_NAME:
Cuando se ejecute a nivel local, el proyecto de funciones incluirá un local.settings.json archivo, donde se almacenarán las variables de entorno en el objeto Values.
Cuando se ejecute en Azure, la aplicación de funciones permitirá establecer usos de la configuración de la aplicación, como cadenas de conexión de servicio, y expondrá estos valores como variables de entorno durante la ejecución.
Hay varias maneras de agregar, actualizar y eliminar opciones de configuración de la aplicación de función:
Para aplicar los cambios realizados en la configuración de la aplicación de funciones, es necesario reiniciar la aplicación de funciones.
Variables de entorno de trabajo
Hay varias variables de entorno de Functions específicas de Node.js:
languageWorkers__node__arguments
Esta configuración permite especificar argumentos personalizados al iniciar el proceso de Node.js. A menudo se usa localmente para iniciar el trabajo en modo de depuración, pero también se puede usar en Azure si necesita argumentos personalizados.
Advertencia
Si es posible, evite el uso de languageWorkers__node__arguments en Azure porque puede tener un efecto negativo en el tiempo de inicio en frío. En lugar de usar trabajos iniciados previamente, el tiempo de ejecución debe iniciar un nuevo trabajo desde cero con los argumentos personalizados.
logging__logLevel__Worker
Esta configuración ajusta el nivel de registro predeterminado para los registros de trabajo específicos de Node.js. De forma predeterminada, solo se muestran los registros de advertencias o errores, pero puede establecerla en information o debug para ayudar a diagnosticar problemas con el trabajo de Node.js. Para más información, consulte Configuración de los niveles de registro.
Módulos ECMAScript (versión preliminar)
Nota
Los módulos ECMAScript son actualmente una característica en vista previa en Node.js 14 y siguientes en Azure Functions.
Los módulos ECMAScript (módulos ES) son el nuevo sistema de módulos estándar oficial de Node.js. Hasta ahora, en los ejemplos de código de este artículo se usa la sintaxis CommonJS. Al ejecutar Azure Functions en Node.js 14 o una versión posterior, puede optar por escribir las funciones mediante la sintaxis de los módulos ES.
Para usar los módulos ES en una función, cambie su nombre de archivo para usar una extensión .mjs. El siguiente archivo index.mjs es una función desencadenada por HTTP que usa la sintaxis de los módulos ES para importar la biblioteca uuid y devolver un valor.
Las propiedades de function.jsonscriptFile y entryPoint pueden usarse para configurar la ubicación y el nombre de la función exportada. La propiedad scriptFile es necesaria cuando se usa TypeScript y se debe apuntar al JavaScript compilado.
Usar scriptFile
De forma predeterminada, se ejecuta una función de JavaScript desde index.js, un archivo que comparte el mismo directorio primario que su archivo function.json correspondiente.
scriptFile se puede usar para obtener una estructura de carpetas que tenga el aspecto del ejemplo siguiente:
En el modelo v3, una función debe exportarse con module.exports para que se pueda encontrar y ejecutar. De forma predeterminada, la función que se ejecuta cuando se desencadena es la única exportación de ese archivo, la exportación denominada run o la exportación denominada index. El ejemplo siguiente establece entryPoint en function.json un valor personalizado, "logHello":
Se recomienda usar VS Code para la depuración local, que inicia automáticamente el proceso de Node.js en modo de depuración y se adjunta automáticamente al proceso. Para obtener más información, consulte Ejecución local de la función.
Si usa una herramienta diferente para la depuración o quiere iniciar manualmente el proceso de Node.js en modo de depuración, agregue "languageWorkers__node__arguments": "--inspect" después de Values en local.settings.json. El argumento --inspect indica a Node.js que escuche un cliente de depuración, en el puerto 9229 de forma predeterminada. Para obtener más información, consulte la guía de depuración de Node.js.
Recomendaciones
En esta sección se describen varios patrones impactantes para aplicaciones de Node.js que recomendamos seguir.
Elección de los planes de App Service de una sola vCPU
Al crear una aplicación de función que usa el plan de App Service, se recomienda que seleccione un plan de una sola vCPU, en lugar de un plan con varias vCPU. En la actualidad, Functions ejecuta funciones de Node.js con más eficacia en VM con una sola vCPU. El uso de máquinas virtuales más grandes no producirá las mejoras de rendimiento esperadas. Cuando sea necesario, puede escalar horizontalmente de forma manual mediante la adición de más instancias de máquina virtual de una sola vCPU o bien puede habilitar el escalado automático. Para obtener más información, consulte Escalación del recuento de instancias de forma manual o automática.
Ejecución desde un archivo de paquete
Al desarrollar Azure Functions en el modelo de hospedaje sin servidor, los arranques en frío son una realidad. Arranque en frío hace referencia a la primera vez en que su aplicación de funciones se inicia después de un período de inactividad, tardando más tiempo en iniciarse. Especialmente para las aplicaciones de Node.js con árboles de dependencias de gran tamaño, el arranque en frío puede ser importante. Para acelerar el proceso de arranque en frío, ejecute sus funciones como un archivo de paquete cuando sea posible. Muchos métodos de implementación usan este modelo de forma predeterminada, pero si experimentase numerosos arranques en frío, debería hacer alguna comprobación para asegurarse de que se esté ejecutando de esta manera.
Uso de un único cliente estático
Cuando use un cliente específico del servicio en una aplicación de Azure Functions, no cree un cliente con cada invocación de función, ya que puede alcanzar los límites de conexiones. En su lugar, cree un único cliente estático en el ámbito global. Para más información, consulte Administrar conexiones en Azure Functions.
Uso de async y await
Al escribir funciones de Azure en Node.js, deberá escribir el código mediante las palabras clave async y await. El hecho de escribir el código con async y await en lugar de usar devoluciones de llamada o .then y .catch con promesas ayuda a evitar dos problemas comunes:
El inicio de excepciones no detectadas que bloquean el proceso de Node.js, que puede afectar a la ejecución de otras funciones.
Comportamiento inesperado, como la ausencia de registros de context.log debido a llamadas asincrónicas que no se esperan correctamente.
En el ejemplo siguiente, se invoca el método asincrónico fs.readFile con una función de devolución de llamada error-first como segundo parámetro. Este código provoca los dos problemas mencionados anteriormente. Una excepción no detectada explícitamente en el ámbito correcto puede bloquear todo el proceso (problema 1). Devolver sin asegurarse de que la devolución de llamada ha finalizado significa que la respuesta http a veces tendrá un cuerpo vacío (incidencia n.º 2).
// DO NOT USE THIS CODEconst { app } = require('@azure/functions');
const fs = require('fs');
app.http('httpTriggerBadAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
let fileData;
fs.readFile('./helloWorld.txt', (err, data) => {
if (err) {
context.error(err);
// BUG #1: This will result in an uncaught exception that crashes the entire processthrow err;
}
fileData = data;
});
// BUG #2: fileData is not guaranteed to be set before the invocation endsreturn { body: fileData };
},
});
TypeScript
// DO NOT USE THIS CODEimport { app, HttpRequest, HttpResponseInit, InvocationContext } from'@azure/functions';
import * as fs from'fs';
exportasyncfunctionhttpTriggerBadAsync(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
let fileData: Buffer;
fs.readFile('./helloWorld.txt', (err, data) => {
if (err) {
context.error(err);
// BUG #1: This will result in an uncaught exception that crashes the entire processthrow err;
}
fileData = data;
});
// BUG #2: fileData is not guaranteed to be set before the invocation endsreturn { body: fileData };
}
app.http('httpTriggerBadAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: httpTriggerBadAsync,
});
En el ejemplo siguiente, se invoca el método asincrónico fs.readFile con una función de devolución de llamada error-first como segundo parámetro. Este código provoca los dos problemas mencionados anteriormente. Una excepción no detectada explícitamente en el ámbito correcto puede bloquear todo el proceso (problema 1). Llamar al método en desuso context.done() fuera del ámbito de la devolución de llamada puede indicar que la función ha terminado antes de que se lea el archivo (problema 2). En este ejemplo, una llamada a context.done() demasiado pronto provoca la ausencia de las entradas de registro que empiezan por Data from file:.
// NOT RECOMMENDED PATTERNconst fs = require('fs');
module.exports = function (context) {
fs.readFile('./hello.txt', (err, data) => {
if (err) {
context.log.error('ERROR', err);
// BUG #1: This will result in an uncaught exception that crashes the entire processthrow err;
}
context.log(`Data from file: ${data}`);
// context.done() should be called here
});
// BUG #2: Data is not guaranteed to be read before the Azure Function's invocation ends
context.done();
}
TypeScript
// NOT RECOMMENDED PATTERNimport { AzureFunction, Context } from"@azure/functions";
import * as fs from'fs';
const trigger1: AzureFunction = function (context: Context): void{
fs.readFile('./hello.txt', (err, data) => {
if (err) {
context.log.error('ERROR', err);
// BUG #1: This will result in an uncaught exception that crashes the entire processthrow err;
}
context.log(`Data from file: ${data}`);
// context.done() should be called here
});
// BUG #2: Data is not guaranteed to be read before the Azure Function's invocation ends
context.done();
}
exportdefault trigger1;
Use las palabras clave async y await para ayudar a evitar ambos problemas. La mayoría de las API del ecosistema de Node.js se han convertido para admitir promesas de alguna forma. Por ejemplo, a partir de la versión 14, Node.js proporciona una API fs/promises para reemplazar la API de devolución de llamada fs.
En el ejemplo siguiente, las excepciones no controladas iniciadas durante la ejecución de la función solo devolverán un error para la invocación individual que generó una excepción. La palabra clave await significa que los pasos después de readFile solo se ejecutarán una vez finalizado.
// Recommended patternconst fs = require('fs/promises');
module.exports = asyncfunction (context) {
let data;
try {
data = await fs.readFile('./hello.txt');
} catch (err) {
context.log.error('ERROR', err);
// This rethrown exception will be handled by the Functions Runtime and will only fail the individual invocationthrow err;
}
context.log(`Data from file: ${data}`);
}
TypeScript
// Recommended patternimport { AzureFunction, Context } from"@azure/functions";
import * as fs from'fs/promises';
const trigger1: AzureFunction = asyncfunction (context: Context): Promise<void> {
let data: Buffer;
try {
data = await fs.readFile('./hello.txt');
} catch (err) {
context.log.error('ERROR', err);
// This rethrown exception will be handled by the Functions Runtime and will only fail the individual invocationthrow err;
}
context.log(`Data from file: ${data}`);
}
exportdefault trigger1;
Únase a la serie de reuniones para crear soluciones de inteligencia artificial escalables basadas en casos de uso reales con compañeros desarrolladores y expertos.
En esta ruta de aprendizaje, descubra Azure Functions que crean sistemas de proceso a petición orientados a eventos mediante la lógica del lado servidor para crear arquitecturas sin servidor.
Aprenda a desarrollar aplicaciones Node.js sin servidor mediante Azure Functions. En esta guía se presentan las tecnologías sin servidor de Azure, lo que le permite crear puntos de conexión HTTP escalables y a petición con JavaScript y TypeScript.
En este artículo se muestra cómo actualizar las aplicaciones de funciones existentes que se ejecutan en la versión 3 del modelo de programación de Node.js a la versión 4.
Obtenga información sobre cómo crear una función de TypeScript y, a continuación, publicar el proyecto de Node.js local en el hospedaje sin servidor de Azure Functions con la extensión de Azure Functions en Visual Studio Code.
Obtenga información sobre cómo crear una función de JavaScript y, a continuación, publicar el proyecto de Node.js local en el hospedaje sin servidor de Azure Functions con la extensión de Azure Functions en Visual Studio Code.
Aprenda a instalar módulos de Node en la aplicación de Azure Functions y a expandir las funcionalidades de la lógica. En primer lugar, instalará una biblioteca desde el registro de npm para manipular fechas. A continuación, importará la biblioteca en la lógica y la usará para formar las fechas de una función HTTP GET. Por último, desencadenará la función y dará formato a las fechas de expiración de los productos. Recursos adicionales:Referencia de JavaScript para Azure Functions: https://docs.micr
Aprenda a crear una función de JavaScript desde la línea de comandos y, luego, a publicar el proyecto de Node.js local en el hospedaje sin servidor en Azure Functions.