Migración a la versión 4 del modelo de programación de Node.js para Azure Functions

En este artículo se describen las diferencias entre la versión 3 y la versión 4 del modelo de programación de Node.js y cómo actualizar una aplicación existente de la versión 3. Si quiere crear una aplicación nueva de la versión 4 en lugar de actualizar una aplicación existente de la versión 3, consulte el tutorial para Visual Studio Code (VS Code) o Azure Functions Core Tools. En este artículo se usan alertas de “sugerencias” para resaltar las acciones concretas más importantes que debe realizar para actualizar la aplicación.

La versión 4 está diseñada para proporcionar a los desarrolladores Node.js las siguientes ventajas:

  • Proporcionar una experiencia familiar e intuitiva a los desarrolladores de Node.js.
  • Hacer que la estructura de los archivos sea flexible con compatibilidad con la personalización completa.
  • Cambiar a un enfoque centrado en el código para definir la configuración de funciones.

Consideraciones

  • 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.

Requisitos

La versión 4 del modelo de programación de Node.js requiere las siguientes versiones mínimas:

Inclusión del paquete npm

En la versión 4, el paquete npm @azure/functions contiene el código fuente principal que respalda el modelo de programación de Node.js. En versiones anteriores, ese código se entregaba directamente en Azure y el paquete npm solo tenía los tipos de TypeScript. Ahora debe incluir este paquete para las aplicaciones de TypeScript y JavaScript. Puede incluir el paquete para las aplicaciones existentes de la versión 3, pero no es necesario.

Sugerencia

Asegúrese de que el paquete @azure/functions aparezca en la sección dependencies (no devDependencies) del archivo package.json. Puede instalar la versión 4 mediante el siguiente comando:

npm install @azure/functions

Definición del punto de entrada de la aplicación

En la versión 4 del modelo de programación, puede estructurar el código de la forma que desee. Los únicos archivos que necesita en la raíz de la aplicación son host.json y package.json.

De lo contrario, debe definir la estructura de archivos; para ello, debe establecer el campo main en el archivo package.json. Puede establecer el campo main en un único archivo o en varios archivos mediante un patrón global. En la tabla siguiente se muestran valores de ejemplo para el main campo:

Ejemplo Descripción
src/index.js Registrar funciones desde un único archivo raíz.
src/functions/*.js Registre cada función desde su propio archivo.
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.
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.

Sugerencia

Asegúrese de definir un campo main en el archivo package.json.

Cambio del orden de los argumentos

La entrada del desencadenador, en lugar del contexto de invocación, ahora es el primer argumento para el controlador de funciones. El contexto de invocación, que ahora es el segundo argumento, se ha simplificado en la versión 4 y no es tan necesario como la entrada del desencadenador. Puede dejarlo desactivado si no lo está usando.

Sugerencia

Cambie el orden de los argumentos. Por ejemplo, si usa un desencadenador HTTP, cambie (context, request) a (request, context) o simplemente (request) si no usa el contexto.

Definición de la función en el código

Ya no tiene que crear y mantener esos archivos de configuración function.json independientes. Ahora puede definir completamente las funciones directamente en los archivos TypeScript o JavaScript. Además, muchas propiedades ahora tienen valores predeterminados para que no tenga que especificarlas cada vez.

const { app } = require('@azure/functions');

app.http('httpTrigger1', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        context.log(`Http function processed request for url "${request.url}"`);

        const name = request.query.get('name') || (await request.text()) || 'world';

        return { body: `Hello, ${name}!` };
    },
});
import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions';

export async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
    context.log(`Http function processed request for url "${request.url}"`);

    const name = request.query.get('name') || (await request.text()) || 'world';

    return { body: `Hello, ${name}!` };
}

app.http('httpTrigger1', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: httpTrigger1,
});

Sugerencia

Mueva la configuración del archivo function.json al código. El tipo del desencadenador se corresponde con un método en el objeto app del nuevo modelo. Por ejemplo, si usa un tipo httpTrigger en function.json, llame a app.http() en el código para registrar la función. Si usa timerTrigger, llame a app.timer().

Revisión del uso del contexto

En la versión 4, el objeto context se simplifica para reducir la duplicación y facilitar la escritura de pruebas unitarias. Por ejemplo, hemos simplificado la entrada y la salida principales para que solo se acceda a ellas como argumento y valor devuelto del controlador de funciones.

Ya no puede acceder a la entrada y salida principales en el objeto context, pero todavía debe acceder a las entradas y salidas secundarias en el objeto context. Para obtener más información sobre las entradas y salidas secundarias, consulte la guía para desarrolladores de Node.js.

Obtención de la entrada principal como argumento

La entrada principal también se denomina desencadenador y es la única entrada o salida necesaria. Debe tener solo un desencadenador.

La versión 4 solo admite una manera de obtener la entrada del desencadenador, como primer argumento:

async function httpTrigger1(request, context) {
  const onlyOption = request;
async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
  const onlyOption = request;

Sugerencia

Asegúrese de que no está usando context.req o context.bindings para obtener la entrada.

Definición de la salida principal como valor devuelto

La versión 4 solo admite una forma de definir la salida principal, a través del valor devuelto:

return { 
  body: `Hello, ${name}!` 
};
async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
    // ...
    return { 
      body: `Hello, ${name}!` 
    };
}

Sugerencia

Asegúrese de que siempre devuelve la salida en el controlador de funciones, en lugar de establecerla con el objeto context.

Registro de contexto

En la versión 4, los métodos de registro se movieron al objeto raíz context , como se muestra en el ejemplo siguiente. Para obtener más información sobre el registro, consulte la guía para desarrolladores de Node.js.

context.log('This is an info log');
context.error('This is an error');
context.warn('This is an error');

Creación de un contexto de prueba

La versión 3 no admite la creación de un contexto de invocación fuera del entorno de ejecución de Azure Functions, por lo que la creación de pruebas unitarias puede ser difícil. La versión 4 permite crear una instancia del contexto de invocación, aunque la información durante las pruebas no se detalla a menos que la agregue usted mismo.

const testInvocationContext = new InvocationContext({
  functionName: 'testFunctionName',
  invocationId: 'testInvocationId'
});

Revisión del uso de tipos HTTP

Los tipos de solicitud y respuesta HTTP ahora son un subconjunto del estándar de captura. Ya no son exclusivos de Azure Functions.

Los tipos usan el paquete undici en Node.js. Este paquete sigue el estándar de captura y actualmente se está integrando en el núcleo de Node.js.

HttpRequest

  • Cuerpo. Puede acceder al cuerpo mediante un método específico del tipo que desea recibir:

    const body = await request.text();
    const body = await request.json();
    const body = await request.formData();
    const body = await request.arrayBuffer();
    const body = await request.blob();
    
  • Encabezado:

    const header = request.headers.get('content-type');
    
  • Parámetro de consulta:

    const name = request.query.get('name');
    

HttpResponse

  • Estado:

    return { status: 200 };
    
  • Cuerpo:

    Use la body propiedad para devolver la mayoría de los tipos como o stringBuffer:

    return { body: "Hello, world!" };
    

    Use la jsonBody propiedad para obtener la manera más sencilla de devolver una respuesta JSON:

    return { jsonBody: { hello: "world" } };
    
  • Encabezado. Puede establecer el encabezado de dos maneras, en función de si usa la clase HttpResponse o la interfaz HttpResponseInit:

    const response = new HttpResponse();
    response.headers.set('content-type', 'application/json');
    return response;
    
    return {
      headers: { 'content-type': 'application/json' }
    };
    

Sugerencia

Actualice cualquier lógica mediante los tipos de solicitud o respuesta HTTP para que coincidan con los nuevos métodos.

Sugerencia

Actualice cualquier lógica mediante los tipos de solicitud o respuesta HTTP para que coincidan con los nuevos métodos. Debe obtener errores de compilación de TypeScript para ayudarle a identificar si usa métodos antiguos.

Solución de problemas

Consulte la guía de solución de problemas de Node.js.