Référence du développeur Node.js pour Azure Functions

Cette référence explique comment développer Azure Functions en utilisant JavaScript et TypeScript avec le @azure/functions package npm. Pour un aperçu général des concepts Azure Functions partagés dans toutes les langues, consultez la référence développeur Azure Functions.

Ressource Lien
Créez votre première fonction JavaScript Visual Studio Code/CLI
Créez votre première fonction TypeScript Visual Studio Code/CLI
Scénarios et exemples JavaScript/TypeScript
Référence d’API @azure/functions API

Remarque

Cet article présente le contenu d’une version spécifique du modèle de programmation basé sur le sélecteur en haut de la page. La version que vous choisissez devrait correspondre à la version de votre @azure/functions package npm. On ne peut pas mélanger les fonctions v3 et v4 dans la même application. Si vous n’avez pas le paquet dans votre package.json, la valeur par défaut est v3.

Modèle de programmation

Azure Functions for Node.js prend en charge deux versions de modèles de programmation. Les nouveaux projets devraient utiliser la v4.

Fonctionnalité V4 (recommandé) v3
Status GA GA (maintenance)
@azure/functions paquet 4.x 3.x
Enregistrement de fonction Centré sur le code (app.http(), app.timer()) Basé sur des fichiers (function.json)
Structure de fichiers Flexible Structure fixe (un dossier par fonction)
Version du runtime Functions 4.25+ 4.x
Versions Node.js 24.x, 22.x 24.x, 22.x

Dans le modèle de programmation Node.js v4, vous enregistrez des fonctions en important l’objet app depuis @azure/functions et en appelant des méthodes propres à chaque déclencheur. Les fonctions sont définies directement dans votre code avec une structure de fichiers flexible. Chaque fonction possède un déclencheur unique qui lance son exécution et peut également avoir des liaisons, qui sont des connexions déclaratives vers d’autres services pour lire ou écrire des données d’entrée. Pour plus d’informations, consultez Déclencheurs et liaisons.

Dans le modèle v4, vous :

  • Enregistrer des fonctions en utilisant des méthodes spécifiques au déclencheur comme app.http(), app.timer(), et app.storageQueue().
  • Accède à l’entrée déclencheuse comme premier argument pour ton gestionnaire (par exemple, HttpRequest).
  • Retournez directement le résultat principal de la fonction de traitement.
  • Utilisez-le context.extraInputs.get() pour lire des liaisons d’entrée supplémentaires comme Stockage Blob.
  • Utilisez context.extraOutputs.set() pour écrire sur des liaisons de sortie supplémentaires comme les files d’attente.
  • Chaque fonction a exactement un déclencheur, mais peut avoir plusieurs entrées et sorties supplémentaires.
  • Vous pouvez mettre en cache les données dans des variables globales pour les réutiliser entre les invocations, mais ne comptez pas sur cet état pour persister. L’environnement d’exécution peut redémarrer votre processus de travail à tout moment.

Dans le modèle de programmation Node.js v3, vous définissez chaque fonction en utilisant un function.json fichier de configuration et le code JavaScript ou TypeScript correspondant. Vous organisez les fonctions dans des dossiers séparés avec des structures de fichiers spécifiques. Chaque fonction possède un déclencheur unique qui lance son exécution et peut également avoir des liaisons, qui sont des connexions déclaratives vers d’autres services pour lire ou écrire des données d’entrée. Pour plus d’informations, consultez Déclencheurs et liaisons.

Dans le modèle v3, vous :

  • Définissez les déclencheurs et les liaisons dans un function.json fichier. À utiliser direction: "in" pour les entrées et direction: "out" les sorties.
  • Accède à l’entrée déclencheuse comme second argument à ton handler, ou lis-le depuis context.bindings.
  • Définissez les sorties en attribuant des valeurs à context.bindings (par exemple, context.bindings.outputQueue). Pour HTTP, utilisez context.res.
  • Les projets TypeScript nécessitent la propriété scriptFile dans function.json, qui pointe vers le fichier JavaScript compilé.
  • Chaque fonction a exactement un déclencheur, mais peut comporter plusieurs liaisons d’entrée et de sortie.
  • Vous pouvez mettre en cache les données dans des variables globales pour les réutiliser entre les invocations, mais ne comptez pas sur cet état pour persister. L’environnement d’exécution peut redémarrer votre processus de travail à tout moment.

Examples

Voici une fonction simple qui répond à une requête HTTP :

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

app.http('httpTrigger', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        const name = request.query.get('name') || 'World';
        context.log('HTTP trigger function processed a request.');

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

L’exemple suivant non HTTP utilise un déclencheur de minuterie :

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

app.timer('cleanupTimer', {
  schedule: '0 */5 * * * *',
  handler: async (myTimer, context) => {
    context.log('Timer trigger function ran at', new Date().toISOString());
  }
});

L’exemple suivant illustre un déclencheur HTTP avec une liaison de sortie vers une file d’attente :

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

const queueOutput = output.storageQueue({
  queueName: 'work-items',
  connection: 'AzureWebJobsStorage'
});

app.http('submitWorkItem', {
  methods: ['POST'],
  extraOutputs: [queueOutput],
  handler: async (request, context) => {
    const body = await request.json();
    context.extraOutputs.set(queueOutput, JSON.stringify(body));
    return { status: 202, jsonBody: { accepted: true } };
  }
});

Voici une fonction simple qui répond à une requête HTTP :

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}
module.exports = async function (context, req) {
    const name = (req.query.name || (req.body && req.body.name)) || 'World';
    context.log('HTTP trigger function processed a request.');

    context.res = {
        body: `Hello, ${name}!`
    };
};

L’exemple suivant non HTTP utilise un déclencheur de minuterie :

{
  "bindings": [
    {
      "name": "myTimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 */5 * * * *"
    }
  ]
}
module.exports = async function (context, myTimer) {
    context.log('Timer trigger function ran at', new Date().toISOString());
};

L’exemple suivant illustre un déclencheur HTTP avec une liaison de sortie vers une file d’attente :

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["post"]
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "workItems",
      "queueName": "work-items",
      "connection": "AzureWebJobsStorage"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}
module.exports = async function (context, req) {
    const payload = req.body || {};
    context.bindings.workItems = JSON.stringify(payload);
    context.res = {
        status: 202,
        body: { accepted: true }
    };
};

Création de votre application de fonction

Cette section couvre les composants essentiels pour créer et structurer votre application de fonctions Node, y compris la @azure/functions bibliothèque, la structure du projet et la gestion des paquets.

Bibliothèque @azure/functions

La @azure/functions bibliothèque TypeScript/JavaScript fournit les types et fonctions de base que vous utilisez pour interagir avec l’exécution Azure Functions. Pour afficher tous les types et méthodes disponibles, visitez l’API@azure/functions.

Votre code de fonction peut être utilisé @azure/functions pour :

  • Enregistrer les fonctions et définir les déclencheurs (modèle v4).
  • Accédez aux données d’entrée de déclenchement fortement typées (par exemple, HttpRequest, Timer).
  • Créez des valeurs de sortie typées (telles que HttpResponseInit).
  • Interagir avec le contexte et les données de liaison fournis par l’environnement d’exécution.

Si vous utilisez @azure/functions dans votre application, incluez-le dans vos dépendances de projet :

{
  "dependencies": {
    "@azure/functions": "^4.0.0"
  }
}

Remarque

La @azure/functions bibliothèque définit la surface de programmation pour Node.js Azure Functions, mais ce n'est pas un SDK généraliste. Utilisez-le spécifiquement pour la création et l’exécution de fonctions dans le runtime Azure Functions.

Configuration de TypeScript

Pour une expérience de développement TypeScript optimale, assurez-vous que votre tsconfig.json comporte la configuration appropriée :

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "outDir": "dist",
    "rootDir": ".",
    "sourceMap": true,
    "strict": false,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Structure de dossiers

Un projet JavaScript nécessite la structure de dossiers présentée dans l’exemple suivant :

<project_root>/
 | - .vscode/
 | - node_modules/
 | - myFirstFunction/
 | | - index.js
 | | - function.json
 | - mySecondFunction/
 | | - index.js
 | | - function.json
 | - .funcignore
 | - host.json
 | - local.settings.json
 | - package.json

Le dossier principal du projet <project_root> peut contenir les fichiers suivants :

  • .vscode/ : (Facultatif) Contient la configuration Visual Studio Code stockée. Pour plus d’informations, consultez Visual Studio Code paramètres.
  • myFirstFunction/function.json : contient la configuration du déclencheur, des entrées et des sorties de la fonction. Le nom du répertoire détermine le nom de votre fonction.
  • myFirstFunction/index.js : stocke le code de votre fonction. Pour changer ce chemin de fichier par défaut, consultez Utilisation de scriptFile.
  • .funcignore : (facultatif) déclare les fichiers qui ne doivent pas être publiés sur Azure. Habituellement, ce fichier contient .vscode/ pour ignorer les paramètres de votre éditeur, tester / ignorer les cas de test, et local.settings.json empêcher la publication des paramètres locaux de l’application.
  • host.json : contient les options de configuration qui affectent toutes les fonctions d’une instance d’application de fonction. Ce fichier est publié sur Azure. Toutes les options ne sont pas prises en charge lors de l’exécution locale. Pour en savoir plus, consultez la section host.json.
  • local.settings.json : utilisé pour stocker les paramètres d’application et les chaînes de connexion lors d’une exécution en local. Ce fichier n'est pas publié dans Azure. Pour en savoir plus, consultez la section local.settings.file.
  • package.json: Contient des options de configuration comme une liste des dépendances des paquets, le point d’entrée principal et des scripts.

Un projet JavaScript suit la structure de dossiers recommandée dans l’exemple suivant :

<project_root>/
 | - .vscode/
 | - node_modules/
 | - src/
 | | - functions/
 | | | - myFirstFunction.js
 | | | - mySecondFunction.js
 | - test/
 | | - functions/
 | | | - myFirstFunction.test.js
 | | | - mySecondFunction.test.js
 | - .funcignore
 | - host.json
 | - local.settings.json
 | - package.json

Le dossier principal du projet <project_root> peut contenir les fichiers suivants :

  • .vscode/ : (Facultatif) Contient la configuration Visual Studio Code stockée. Pour plus d’informations, consultez Visual Studio Code paramètres.
  • src/functions/ : l’emplacement par défaut pour toutes les fonctions et leurs déclencheurs et liaisons associés.
  • test/ : (Facultatif) Contient les cas de test de votre application de fonction.
  • .funcignore : (facultatif) déclare les fichiers qui ne doivent pas être publiés sur Azure. Habituellement, ce fichier contient .vscode/ pour ignorer les paramètres de votre éditeur, tester / ignorer les cas de test, et local.settings.json empêcher la publication des paramètres locaux de l’application.
  • host.json : contient les options de configuration qui affectent toutes les fonctions d’une instance d’application de fonction. Ce fichier est publié sur Azure. Toutes les options ne sont pas prises en charge lors de l’exécution locale. Pour en savoir plus, consultez la section host.json.
  • local.settings.json : utilisé pour stocker les paramètres d’application et les chaînes de connexion lors d’une exécution en local. Ce fichier n'est pas publié dans Azure. Pour en savoir plus, consultez la section local.settings.file.
  • package.json: Contient des options de configuration comme une liste des dépendances des paquets, le point d’entrée principal et des scripts.

Gestion des packages

Une gestion efficace des paquets est cruciale pour Node.js Azure Functions projets. Cette section traite de la gestion des dépendances, de la configuration des paquets et des meilleures pratiques pour maintenir les dépendances de vos applications de fonction.

Gestion des dépendances

Tous Node.js Azure Functions projets utilisent NPM pour la gestion des paquets. Votre package.json fichier définit la configuration du projet, les dépendances et les scripts nécessaires pour construire et exécuter vos fonctions.

Structure essentielle du fichier package.json :

{
  "name": "my-functions-app",
  "version": "1.0.0",
  "description": "Azure Functions Node.js app",
  "main": "src/index.js",
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "prestart": "npm run build",
    "start": "func start",
    "test": "jest"
  },
  "dependencies": {
    "@azure/functions": "^4.0.0"
  },
  "devDependencies": {
    "@azure/functions-core-tools": "^4.0.4670",
    "@types/node": "^18.0.0",
    "typescript": "^4.0.0",
    "jest": "^29.0.0"
  }
}

Runtime vs. dépendances de développement

Séparez vos dépendances de manière appropriée :

Dépendances à l’exécution (dependencies) :

  • @azure/functions: La bibliothèque principale Azure Functions
  • Bibliothèques de logique métier (lodash, axios et packages similaires)
  • Pilotes de base de données (mongodb, mssql et packages similaires)
  • Kit de développement logiciel (SDK) Azure paquets (@azure/storage-blob, @azure/cosmos, et paquets similaires)

Dépendances de développement (devDependencies) :

  • Compilateur TypeScript et définitions de types
  • Frameworks de test (Jest, Mocha)
  • Outils de build et linters
  • Azure Functions Core Tools (pour le développement local)

Paquets spécifiques à TypeScript

Pour les projets TypeScript, incluez ces dépendances essentielles de développement :

{
  "devDependencies": {
    "@types/node": "^18.0.0",
    "typescript": "^4.0.0",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0"
  }
}

Sécurité et mises à jour

Mettez régulièrement à jour vos dépendances pour traiter les vulnérabilités de sécurité :

# Check for outdated packages
npm outdated

# Update packages
npm update

# Audit for security issues
npm audit
npm audit fix

Exécution et débogage

Cette section couvre le développement local, les techniques de débogage et les stratégies de test pour Node.js Azure Functions.

Configuration du développement local

Configuration requise :

Étapes d’installation :

  1. Installer les dépendances :

    npm install
    
  2. Compiler des projets TypeScript :

    npm run build
    
  3. Démarrez l’exécution locale :

    npm start
    # or directly:
    func start
    

Configuration de l’environnement

Configurez votre environnement de développement local en utilisant local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "NODE_ENV": "development",
    "CUSTOM_ENV_VARIABLE": "local-value"
  },
  "Host": {
    "LocalHttpPort": 7071,
    "CORS": "*",
    "CORSCredentials": false
  }
}

Débogage

Débogage de Visual Studio Code :

Créez .vscode/launch.json :

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to Node Functions",
      "type": "node",
      "request": "attach",
      "port": 9229,
      "preLaunchTask": "func: host start"
    }
  ]
}

Créez .vscode/tasks.json :

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "func",
      "label": "func: host start",
      "command": "host start",
      "problemMatcher": "$func-node-watch",
      "isBackground": true,
      "options": {
        "cwd": "${workspaceFolder}"
      }
    }
  ]
}

Débogage en ligne de commande :

# Start with debugging enabled
func start --p <port>

# For TypeScript, ensure you build first
npm run build
func start --p 9229

Deployment

Cette section couvre les stratégies de déploiement, l’intégration CI/CD et les meilleures pratiques de production pour Node.js Azure Functions.

Méthodes de déploiement

1. Déploiement de Visual Studio Code :

  • Installez l’extension Azure Functions.
  • Faites un clic droit sur votre application de fonctions dans le panneau Azure.
  • Sélectionnez Déployer sur Function App.

2. Azure Functions Outils de base :

# Deploy to Azure
func azure functionapp publish <FunctionAppName>

# Deploy with custom settings
func azure functionapp publish <FunctionAppName> --build local --publish-local-settings

3. Azure CLI deployment :

# Deploy from local folder
az functionapp deployment source config-zip \
  --resource-group <ResourceGroupName> \
  --name <FunctionAppName> \
  --src <PathToZipFile>

Configuration de production

Paramètres d’application dans Azure :

Configurez les variables d’environnement pour la production :

  • WEBSITE_NODE_DEFAULT_VERSION : à définir sur ~18 ou ~20.
  • FUNCTIONS_WORKER_RUNTIME: défini sur node.
  • Les chaînes de connexion et les clés API comme paramètres sécurisés de l’application.
  • NODE_ENV: défini sur production.

Déclencheurs et liaisons

Azure Functions utilise triggers pour démarrer l’exécution de la fonction et bindings pour connecter votre code à d’autres services tels que le stockage, les files d’attente et les bases de données. Dans le modèle de programmation Node.js, vous déclarez les liaisons différemment selon la version de votre modèle.

Deux types principaux de liaisons existent :

  • Déclencheurs (entrée qui démarre la fonction)
  • Entrées et sorties (sources de données ou destinations supplémentaires)

Pour plus d’informations sur les déclencheurs et les liaisons disponibles, consultez Déclencheurs et liaisons dans Azure Functions.

Exemple : déclencheur de minuteur avec entrée Blob

Cette fonction se déclenche toutes les 10 minutes, lit un Blob en utilisant des entrées supplémentaires, et enregistre le contenu du blob.

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

let CACHED_BLOB_DATA = null;

const blobInput = input.storageBlob({
    connection: 'BLOB_CONNECTION_SETTING',
    path: 'mycontainer/myblob.txt'
});

app.timer('TimerTriggerWithBlob', {
    schedule: '0 */10 * * * *',
    extraInputs: [blobInput],
    handler: async (myTimer, context) => {
        if (CACHED_BLOB_DATA === null) {
            // Read blob content and cache it
            CACHED_BLOB_DATA = context.extraInputs.get(blobInput);
            context.log(`Blob content cached: ${CACHED_BLOB_DATA?.substring(0, 100)}...`);
        }

        context.log(`Timer function executed at: ${new Date().toISOString()}`);
        context.log(`Using cached data of length: ${CACHED_BLOB_DATA?.length || 0}`);
    }
});

Cette fonction se déclenche toutes les 10 minutes, lit un blob en utilisant la configuration des liaisons, et enregistre le contenu du blob.

{
  "scriptFile": "index.js",
  "bindings": [
    {
      "name": "myTimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 */10 * * * *"
    },
    {
      "name": "blobInput",
      "type": "blob",
      "direction": "in",
      "path": "mycontainer/myblob.txt",
      "connection": "AzureWebJobsStorage"
    }
  ]
}
let CACHED_BLOB_DATA = null;

module.exports = async function (context, myTimer) {
    if (CACHED_BLOB_DATA === null) {
        // Read blob content and cache it
        CACHED_BLOB_DATA = context.bindings.blobInput;
        context.log(`Blob content cached: ${CACHED_BLOB_DATA?.substring(0, 100)}...`);
    }

    context.log(`Timer function executed at: ${new Date().toISOString()}`);
    context.log(`Using cached data of length: ${CACHED_BLOB_DATA?.length || 0}`);
};

Exemple : déclencheur HTTP avec sortie de file d’attente

Cette fonction se déclenche sur une requête HTTP, écrit un message dans une file de stockage et renvoie une réponse HTTP.

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

const queueOutput = output.storageQueue({
    connection: 'AzureWebJobsStorage',
    queueName: 'myqueue'
});

app.http('httpTriggerWithQueue', {
    methods: ['GET', 'POST'],
    extraOutputs: [queueOutput],
    handler: async (request, context) => {
        const name = request.query.get('name') || 'World';
        const message = {
            id: context.invocationId,
            name: name,
            timestamp: new Date().toISOString()
        };

        // Write to queue output
        context.extraOutputs.set(queueOutput, JSON.stringify(message));
        context.log(`Message sent to queue: ${JSON.stringify(message)}`);

        return {
            body: `Hello, ${name}! Message queued successfully.`
        };
    }
});

Cette fonction se déclenche sur une requête HTTP, écrit un message dans une file de stockage et renvoie une réponse HTTP.

{
  "scriptFile": "index.js",
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "outputQueue",
      "queueName": "myqueue",
      "connection": "AzureWebJobsStorage"
    }
  ]
}
module.exports = async function (context, req) {
    const name = (req.query.name || (req.body && req.body.name)) || 'World';
    const message = {
        id: context.invocationId,
        name: name,
        timestamp: new Date().toISOString()
    };

    // Write to queue output
    context.bindings.outputQueue = JSON.stringify(message);
    context.log(`Message sent to queue: ${JSON.stringify(message)}`);

    return {
        status: 200,
        body: `Hello, ${name}! Message queued successfully.`
    };
};

Les objets app, trigger, input et output exportés par le module @azure/functions fournissent des méthodes spécifiques au type pour la plupart des types. Pour tous les types qui ne sont pas pris en charge, une méthode generic est fournie pour vous permettre de spécifier manuellement la configuration. La méthode generic peut également être utilisée si vous souhaitez modifier les paramètres par défaut fournis par une méthode spécifique à un type.

L’exemple suivant est une fonction simple déclenchée via HTTP utilisant des méthodes génériques au lieu de méthodes spécifiques au type.

const { app, output, trigger } = require("@azure/functions");

app.generic("helloWorld1", {
  trigger: trigger.generic({
    type: "httpTrigger",
    methods: ["GET", "POST"],
  }),
  return: output.generic({
    type: "http",
  }),
  handler: async (request, context) => {
    context.log(`Http function processed request for url "${request.url}"`);

    return { body: `Hello, world!` };
  },
});

::: fin de zone

Contexte d’appel

Chaque invocation de votre fonction reçoit un objet d’invocation context . Utilisez cet objet pour lire les entrées, définir les sorties, écrire dans les journaux et accéder à diverses métadonnées. Dans le modèle v3, on transmet toujours l’objet contexte comme premier argument à votre handler.

L’objet context comprend les propriétés suivantes :

Propriété Descriptif
invocationId L’identifiant de l’appel de fonction en cours.
executionContext Consultez Contexte d’exécution.
bindings Consultez Liaisons.
bindingData Métadonnées sur l’entrée déclencheuse de cette invocation, à l’exclusion de la valeur elle-même. Par exemple, un déclencheur de hub d’événements a une propriété enqueuedTimeUtc.
traceContext Le contexte pour le suivi distribué. Pour plus d’informations, consultez Trace Context.
bindingDefinitions Configuration de vos entrées et sorties, comme défini dans function.json.
req Consultez Requête HTTP.
res Consultez Réponse HTTP.

context.executionContext

L’objet context.executionContext dispose des propriétés suivantes :

Propriété Descriptif
invocationId L’identifiant de l’appel de fonction en cours.
functionName Le nom de la fonction que vous invoquez. Le nom du dossier contenant le fichier function.json détermine le nom de la fonction.
functionDirectory Dossier contenant le fichier function.json.
retryContext Consultez retryContext.

context.executionContext.retryContext

L’objet context.executionContext.retryContext dispose des propriétés suivantes :

Propriété Descriptif
retryCount Nombre représentant la nouvelle tentative en cours.
maxRetryCount Nombre maximal de nouvelles tentatives d’une exécution. Une valeur de -1 signifie qu’il faut effectuer ces nouvelles tentatives indéfiniment.
exception Exception ayant provoqué la nouvelle tentative.

context.bindings

Utilisez l’objet context.bindings pour lire les entrées ou définir les sorties. L’exemple suivant est un déclencheur de file d’attente de stockage qui sert context.bindings à copier une entrée de blob de stockage vers une sortie de blob de stockage. Le contenu du message de file d’attente remplace {queueTrigger} comme nom de fichier à copier, à l’aide d’une expression de liaison.

{
    "name": "myQueueItem",
    "type": "queueTrigger",
    "direction": "in",
    "connection": "storage_APPSETTING",
    "queueName": "helloworldqueue"
},
{
    "name": "myInput",
    "type": "blob",
    "direction": "in",
    "connection": "storage_APPSETTING",
    "path": "helloworld/{queueTrigger}"
},
{
    "name": "myOutput",
    "type": "blob",
    "direction": "out",
    "connection": "storage_APPSETTING",
    "path": "helloworld/{queueTrigger}-copy"
}
module.exports = async function (context, myQueueItem) {
  const blobValue = context.bindings.myInput;
  context.bindings.myOutput = blobValue;
};

context.done

La méthode context.done est déconseillée. Avant qu’Azure Functions ne prenne en charge les fonctions asynchrones, vous signaliez que votre fonction était terminée en appelant context.done():

module.exports = function (context, request) {
  context.log("this pattern is now deprecated");
  context.done();
};

Supprimez l’appel à context.done(). Marque ta fonction comme asynchrone pour qu’elle renvoie une promesse (même si tu ne fais rien await ). Dès que l’exécution de votre fonction se termine (en d’autres termes, à la résolution de la promesse retournée), le modèle v3 sait que votre fonction est terminée.

module.exports = async function (context, request) {
  context.log("you don't need context.done or an awaited call");
};

Chaque invocation de votre fonction reçoit un objet d’invocation context . Cet objet contient des informations sur votre invocation et les méthodes de journalisation. Dans le modèle v4, on transmet généralement l’objet context comme second argument à votre manipulateur.

La InvocationContext classe inclut les propriétés suivantes :

Propriété Descriptif
invocationId L’identifiant de l’appel de fonction en cours.
functionName Nom de la fonction.
extraInputs Utilisé pour obtenir les valeurs d’entrées supplémentaires. Pour plus d’informations, consultez Entrées et sorties supplémentaires.
extraOutputs Utilisé pour définir les valeurs des sorties supplémentaires. Pour plus d’informations, consultez Entrées et sorties supplémentaires.
retryContext Consultez retryContext.
traceContext Le contexte pour le suivi distribué. Pour plus d’informations, consultez Trace Context.
triggerMetadata Métadonnées relatives à l’entrée de déclencheur pour cet appel, ce qui exclut la valeur elle-même. Par exemple, un déclencheur de hub d’événements a une propriété enqueuedTimeUtc.
options Les options utilisées lors de l’enregistrement de la fonction, après validation et paramètres par défaut, sont explicitement spécifiées.

Contexte de nouvelle tentative

L’objet retryContext dispose des propriétés suivantes :

Propriété Descriptif
retryCount Nombre représentant la nouvelle tentative en cours.
maxRetryCount Nombre maximal de nouvelles tentatives d’une exécution. Une valeur de -1 signifie qu’il faut effectuer ces nouvelles tentatives indéfiniment.
exception Exception ayant provoqué la nouvelle tentative.

Pour plus d’informations, consultez retry-policies.

Journalisation

Dans Azure Functions, utilisez context.log() pour écrire des journaux. Azure Functions s’intègre à Azure Application Insights pour mieux capturer les logs de votre fonction d'application. Application Insights, qui fait partie de Azure Monitor, fournit des fonctionnalités pour la collecte, le rendu visuel et l’analyse des journaux d’application et de vos sorties de trace. Pour plus d’informations, consultez monitoring Azure Functions.

Remarque

Si vous utilisez la méthode alternative Node.js console.log , les journaux au niveau de l’application sont suivis mais ne sont associés à aucune fonction spécifique. Utilisez context pour la journalisation au lieu de console afin que tous les journaux soient associés à une fonction spécifique.

L’exemple suivant écrit un journal au niveau « informations » par défaut, notamment l’ID d’appel :

context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);

Niveaux de journal

Outre la méthode par défaut context.log, utilisez les méthodes suivantes pour écrire des messages de journalisation à des niveaux spécifiques :

Méthode Descriptif
context.log.error() Écrit un événement au niveau de l’erreur dans les journaux.
context.log.warn() Écrit un événement de niveau avertissement dans les journaux.
context.log.info() Écrit un événement de niveau information dans les journaux.
context.log.verbose() Écrit un événement de niveau trace dans les journaux.
Méthode Descriptif
context.trace() Écrit un événement de niveau trace dans les journaux.
context.debug() Écrit un événement de niveau débogage dans les journaux.
context.info() Écrit un événement de niveau information dans les journaux.
context.warn() Écrit un événement de niveau avertissement dans les journaux.
context.error() Écrit un événement au niveau de l’erreur dans les journaux.

Configurer le niveau de journal

Functions vous permet de définir le niveau de seuil pour suivre et consulter les journaux. Pour définir le seuil, utilisez la propriété logging.logLevel dans le fichier host.json. Cette propriété vous permet de définir un niveau par défaut pour toutes les fonctions ou un seuil pour chaque fonction individuelle. Pour plus d’informations, consultez How to configure monitoring for Azure Functions.

Suivre les données personnalisées

Par défaut, Azure Functions écrit la sortie comme des traces dans Application Insights. Pour plus de contrôle, utilisez le SDK Node.js Application Insights pour envoyer des journaux personnalisés, des métriques et des dépendances à votre instance Application Insights.

Remarque

Les méthodes du Kit de développement logiciel (SDK) Application Insights Node.js peuvent changer au fil du temps. Il peut y avoir des différences de syntaxe mineures dans les exemples présentés ici. Pour obtenir les derniers exemples d’utilisation de l’API, consultez la documentation du Kit de développement logiciel (SDK) Application Insights Node.js.

Pour la traçabilité distribuée dans le modèle de programmation Node.js v4, utilisez le @azure/functions-opentelemetry-instrumentation package au lieu du SDK Application Insights. Ce package fournit une instrumentation automatique basée sur OpenTelemetry pour Azure Functions. Pour plus d’informations, consultez le référentiel OpenTelemetry Azure Functions Instrumentation pour Node.js GitHub.

const appInsights = require("applicationinsights");
appInsights.setup();
const client = appInsights.defaultClient;

module.exports = async function (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: new Error("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,
  });
};

Le paramètre tagOverrides définit operation_Id sur l’ID d'appel de la fonction. Ce réglage vous permet de corréler tous les journaux générés automatiquement et personnalisés pour une invocation de fonction donnée.

Déclencheurs HTTP

Les déclencheurs HTTP et webhook ainsi utilisent les objets de requête et de réponse pour représenter les messages HTTP.

Les déclencheurs HTTP et webhook utilisent des objets HttpRequest et HttpResponse pour représenter les messages HTTP. Les classes représentent un sous-ensemble de la norme de récupération (fetch), à l’aide du package undici de Node.js.

Demande HTTP

Accédez à la demande de plusieurs manières :

  • Comme deuxième argument de votre fonction :

    module.exports = async function (context, request) {
        context.log(`Http function processed request for url "${request.url}"`);
    

  • À partir de la propriété context.req :

    module.exports = async function (context, request) {
        context.log(`Http function processed request for url "${context.req.url}"`);
    

  • À partir des liaisons d’entrée nommées : Cette option fonctionne de la même manière que pour n’importe quelle liaison non-HTTP. Le nom de liaison dans function.json doit correspondre à la clé sur context.bindings, ou « request1 » dans l’exemple suivant :

    {
      "name": "request1",
      "type": "httpTrigger",
      "direction": "in",
      "authLevel": "anonymous",
      "methods": ["get", "post"]
    }
    
    module.exports = async function (context, request) {
        context.log(`Http function processed request for url "${context.bindings.request1.url}"`);
    

L’objet HttpRequest dispose des propriétés suivantes :

Propriété Type Descriptif
method string Méthode de requête HTTP utilisée pour appeler cette fonction.
url string URL de requête.
headers Record<string, string> En-têtes de requête HTTP. Cet objet respecte la casse. Utilisez request.getHeader('header-name') à la place, ce qui est insensible à la majuscule.
query Record<string, string> Clés et valeurs de paramètre de chaîne de requête de l’URL.
params Record<string, string> Clés et valeurs des paramètres de routage.
user HttpRequestUser \| null Objet représentant l’utilisateur connecté, via l’authentification Functions, l’authentification SWA ou null lorsqu’aucun utilisateur n’est connecté.
body Buffer \| string \| any Si le type de média est « application/octet-stream » ou « multipart/* », body est une mémoire tampon. Si la valeur est une chaîne analysable en JSON, body est l’objet analysé. Sinon, body est une chaîne.
rawBody string Corps en tant que chaîne. Malgré le nom, cette propriété ne retourne pas un tampon.
bufferBody Buffer Corps en tant que mémoire tampon.

Vous pouvez accéder à la requête comme premier argument à votre gestionnaire pour une fonction déclenchée par HTTP.

async (request, context) => {
    context.log(`Http function processed request for url "${request.url}"`);

L’objet HttpRequest dispose des propriétés suivantes :

Propriété Type Descriptif
method string Méthode de requête HTTP utilisée pour appeler cette fonction.
url string URL de requête.
headers Headers En-têtes de requête HTTP.
query URLSearchParams Clés et valeurs de paramètre de chaîne de requête de l’URL.
params Record<string, string> Clés et valeurs des paramètres de routage.
user HttpRequestUser \| null Objet représentant l’utilisateur connecté, via l’authentification Functions, l’authentification SWA ou null lorsqu’aucun utilisateur n’est connecté.
body ReadableStream \| null Corps en tant que flux accessible en lecture.
bodyUsed boolean Valeur booléenne indiquant si le corps est déjà lu.

Pour accéder au corps d’une demande ou d’une réponse, utilisez les méthodes suivantes :

Méthode Type de retour
arrayBuffer() Promise<ArrayBuffer>
blob() Promise<Blob>
formData() Promise<FormData>
json() Promise<unknown>
text() Promise<string>

Remarque

Vous ne pouvez exécuter les fonctions corporelles qu’une seule fois. Les appels suivants se résolvent avec des chaînes vides ou des ArrayBuffers.

Réponse HTTP

Vous pouvez définir la réponse de plusieurs façons. Par exemple, vous pouvez utiliser :

  • Définir la propriété context.res :

    module.exports = async function (context, request) {
        context.res = { body: `Hello, world!` };
    

  • Retourner la réponse : si votre fonction est asynchrone et que vous définissez le nom de liaison sur $return dans votre function.json, vous pouvez retourner la réponse directement au lieu de la définir sur context.

    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
    
    module.exports = async function (context, request) {
        return { body: `Hello, world!` };
    

  • Définissez la liaison de sortie nommée : Cette option fonctionne de la même manière que pour n’importe quelle liaison non-HTTP. Le nom de liaison dans function.json doit correspondre à la clé sur context.bindings, ou « response1 » dans l’exemple suivant :

    {
      "type": "http",
      "direction": "out",
      "name": "response1"
    }
    
    module.exports = async function (context, request) {
        context.bindings.response1 = { body: `Hello, world!` };
    

  • Appelercontext.res.send() : Cette option est dépréciée. Il appelle context.done() implicitement et vous ne pouvez pas l’utiliser dans une fonction asynchrone.

    module.exports = function (context, request) {
        context.res.send(`Hello, world!`);
    

Si vous créez un objet lors de la définition de la réponse, cet objet doit correspondre à l’interface HttpResponseSimple, qui a les propriétés suivantes :

Propriété Type Descriptif
headers Record<string, string> (facultatif) En-têtes de réponse HTTP.
cookies Cookie[] (facultatif) Cookies de réponse HTTP.
body any (facultatif) Corps de réponse HTTP.
statusCode number (facultatif) Code d’état de la réponse HTTP. Si elle n’est pas définie, la valeur par défaut est 200.
status number (facultatif) Identique à statusCode. Cette propriété est ignorée si statusCode est défini.

Vous pouvez également modifier l’objet context.res sans le remplacer. L’objet context.res par défaut utilise l’interface HttpResponseFull, qui prend en charge les méthodes suivantes en plus des propriétés HttpResponseSimple :

Méthode Descriptif
status() Définit l’état.
setHeader() Définit un champ d’en-tête. REMARQUE :res.set() et res.header() sont aussi soutenus et font la même chose.
getHeader() Obtient un champ de tête. REMARQUE :res.get() est également pris en charge et produit le même effet.
removeHeader() Supprime un en-tête.
type() Définit l’en-tête « content-type ».
send() Cette méthode est déconseillée. Elle définit le corps et appelle context.done() pour indiquer qu’une fonction de synchronisation est terminée. REMARQUE :res.end() est également pris en charge et a le même effet.
sendStatus() Cette méthode est déconseillée. Elle définit le code d’état et appelle context.done() pour indiquer qu’une fonction de synchronisation est terminée.
json() Cette méthode est déconseillée. Il définit le « content-type » sur « application/json », définit le corps et appelle context.done() pour indiquer qu’une fonction de synchronisation est terminée.

Vous pouvez définir la réponse de plusieurs façons. Par exemple, vous pouvez utiliser :

  • Une interface simple avec type HttpResponseInit: Cette option est la manière la plus concise de renvoyer les réponses.

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

Une interface HttpResponseInit possède les propriétés suivantes :

Propriété Type Descriptif
body BodyInit (facultatif) Corps de la réponse HTTP sous la forme de ArrayBuffer, AsyncIterable<Uint8Array>, Blob, FormData, Iterable<Uint8Array>, NodeJS.ArrayBufferView, URLSearchParams, null ou string.
jsonBody any (facultatif) Corps de réponse HTTP sérialisable JSON. Si elle est définie, la propriété HttpResponseInit.body est ignorée au profit de cette propriété.
status number (facultatif) Code d’état de la réponse HTTP. Si elle n’est pas définie, la valeur par défaut est 200.
headers HeadersInit (facultatif) En-têtes de réponse HTTP.
cookies Cookie[] (facultatif) Cookies de réponse HTTP.
  • En tant que classe du type HttpResponse : cette option fournit des méthodes d’assistance pour la lecture et la modification de différentes parties de la réponse, comme les en-têtes.

    const response = new HttpResponse({ body: `Hello, world!` });
    response.headers.set("content-type", "application/json");
    return response;
    

La classe HttpResponse accepte un facultatif HttpResponseInit comme argument de son constructeur et possède les propriétés suivantes :

Propriété Type Descriptif
status number Code d’état de la réponse HTTP.
headers Headers En-têtes de réponse HTTP.
cookies Cookie[] Cookies de réponse HTTP.
body ReadableStream | null Corps en tant que flux accessible en lecture.
bodyUsed boolean Valeur booléenne indiquant si le corps est déjà lu.

Flux HTTP

Les flux HTTP sont une fonctionnalité qui facilite le traitement de données volumineuses, le flux de réponses d’OpenAI, la diffusion de contenu dynamique et la prise en charge d’autres scénarios HTTP fondamentaux. Cela vous permet de diffuser en continu des requêtes vers et des réponses à partir de points de terminaison HTTP dans votre application de fonction Node.js. Utilisez des flux HTTP dans des scénarios où votre application nécessite un échange et une interaction en temps réel entre le client et le serveur via HTTP. Vous pouvez également utiliser des flux HTTP pour obtenir les meilleures performances et la fiabilité optimale pour vos applications lors de l’utilisation de HTTP.

Important

Les flux HTTP ne sont pas pris en charge dans le modèle v3. Mettre à niveau vers le modèle v4 pour utiliser la fonctionnalité de diffusion en continu HTTP. Les types HttpRequest et HttpResponse existants dans le modèle de programmation v4 prennent déjà en charge différentes façons de gérer le corps du message, y compris en tant que flux.

Prérequis

Activer les flux

Procédez comme suit pour activer les flux HTTP dans votre application de fonction dans Azure et dans vos projets locaux :

  1. Si vous envisagez de diffuser en continu de grandes quantités de données, modifiez le paramètre FUNCTIONS_REQUEST_BODY_SIZE_LIMIT dans Azure. La taille maximale par défaut autorisée est 104857600, ce qui limite vos requêtes à environ 100 Mo.

  2. Pour le développement local, ajoutez également FUNCTIONS_REQUEST_BODY_SIZE_LIMIT au fichier local.settings.json.

  3. Ajoutez le code suivant à votre application dans n’importe quel fichier inclus par votre champ principal.

    const { app } = require("@azure/functions");
    
    app.setup({ enableHttpStream: true });
    

Exemples de flux

L’exemple suivant montre une fonction déclenchée par HTTP qui reçoit des données via une requête HTTP POST. La fonction transmet ces données vers un fichier de sortie spécifié :

const { app } = require('@azure/functions');
const { createWriteStream } = require('fs');
const { Writable } = require('stream');

app.http('httpTriggerStreamRequest', {
    methods: ['POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        const writeStream = createWriteStream('<output file path>');
        await request.body.pipeTo(Writable.toWeb(writeStream));

        return { body: 'Done!' };
    },
});

L’exemple suivant montre une fonction déclenchée par HTTP qui diffuse le contenu d’un fichier en réponse aux requêtes HTTP GET entrantes :

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

app.http('httpTriggerStreamResponse', {
    methods: ['GET'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        const body = createReadStream('<input file path>');

        return { body };
    },
});

Pour une application d’exemple prête à l’exécution qui utilise des streams, consultez cet exemple sur GitHub.

Considérations relatives au flux de données

  • Utilisez request.body pour tirer le meilleur parti de l’utilisation des streams. Vous pouvez toujours utiliser des méthodes comme request.text(), qui renvoient toujours le corps sous forme de chaîne de caractères.

Hooks

Le modèle v3 ne supporte pas les crochets. Effectuez une mise à niveau vers le modèle v4 pour utiliser des hooks.

Utilisez un hook pour exécuter du code à différents points du cycle de vie Azure Functions. L’ordre dans lequel vous enregistrez les hooks détermine l’ordre dans lequel ils sont exécutés. Vous pouvez créer des hooks depuis n’importe quel fichier dans votre application. Il existe deux portées de hooks : au niveau de l’application et au niveau de l’invocation.

Crochets d’appel

Les hooks d’invocation s’exécutent une fois par invocation de votre fonction. Un preInvocation crochet s’exécute avant que la fonction ne s’exécute, et un postInvocation crochet fonctionne après que la fonction soit lancée. Par défaut, votre crochet s’exécute pour tous les types de déclencheurs, mais vous pouvez aussi filtrer par type. L’exemple suivant montre comment inscrire un hook d’appel et filtrer par type de déclencheur :

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

// Pre-invocation hook with trigger filtering
app.hook.preInvocation('httpPreInvocation', async (context) => {
  context.hookData.startTime = Date.now();
  context.invocationContext.log(`Pre-invocation hook executed for ${context.invocationContext.functionName}`);

  // Add custom headers or modify function handler if needed
  if (context.functionHandler.name === 'httpTrigger') {
    context.invocationContext.log('HTTP function detected, preparing request processing');
  }
}, {
  filter: ['httpTrigger']
});

// Post-invocation hook
app.hook.postInvocation('httpPostInvocation', async (context) => {
  const duration = Date.now() - context.hookData.startTime;
  context.invocationContext.log(`Function ${context.invocationContext.functionName} completed in ${duration}ms`);

  // Log results or errors
  if (context.error) {
    context.invocationContext.log.error(`Function failed: ${context.error.message}`);
  } else {
    context.invocationContext.log(`Function succeeded with result: ${JSON.stringify(context.result)}`);
  }
}, {
  filter: ['httpTrigger']
});

Le premier argument du gestionnaire de hooks est un objet de contexte spécifique à ce type de hook.

L’objet PreInvocationContext dispose des propriétés suivantes :

Propriété Descriptif
inputs Les arguments que vous transmettez à l’invocation.
functionHandler Le gestionnaire de fonction pour l’appel. Les modifications apportées à cette valeur affectent la fonction elle-même.
invocationContext L’objet de contexte d’appel passé à la fonction.
hookData L’emplacement recommandé pour stocker et partager des données entre des hooks dans la même étendue. Utilisez un nom de propriété unique pour éviter tout conflit avec les données des autres hooks.

L’objet PostInvocationContext dispose des propriétés suivantes :

Propriété Descriptif
inputs Les arguments que vous transmettez à l’invocation.
result Le résultat de la fonction. Les modifications apportées à cette valeur affectent le résultat global de la fonction.
error L’erreur levée par la fonction, ou null/undefined s’il n’y a pas d’erreur. Les modifications apportées à cette valeur affectent le résultat global de la fonction.
invocationContext L’objet de contexte d’appel passé à la fonction.
hookData L’emplacement recommandé pour stocker et partager des données entre des hooks dans la même étendue. Utilisez un nom de propriété unique pour éviter tout conflit avec les données des autres hooks.

Hooks d’application

L’environnement d’exécution exécute les points d’ancrage de l’application une fois par instance de votre application. Il exécute les hooks appStart au démarrage et les hooks appTerminate lors de l’arrêt. Les hooks d’arrêt d’application ont un temps limité pour s’exécuter et ne s’exécutent pas dans tous les scénarios.

Le runtime Azure Functions ne prend actuellement pas en charge la journalisation du contexte en dehors d'une invocation. Utilisez le package npm Application Insights pour journaliser les données pendant les hooks au niveau de l’application.

L’exemple suivant enregistre les hooks d’application  :

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

// Initialize Application Insights for app-level logging
appInsights.setup().start();
const client = appInsights.defaultClient;

// App start hook
app.hook.appStart('appStartup', async (context) => {
  context.hookData.appStartTime = Date.now();
  context.hookData.initializationData = {};

  // Initialize shared resources, database connections, etc.
  client.trackEvent({
    name: 'FunctionAppStarted',
    properties: {
      timestamp: new Date().toISOString(),
      nodeVersion: process.version
    }
  });

  // Set up global configurations
  process.env.APP_INITIALIZED = 'true';
});

// App terminate hook
app.hook.appTerminate('appShutdown', async (context) => {
  const uptime = Date.now() - context.hookData.appStartTime;

  // Cleanup resources, close connections, etc.
  client.trackEvent({
    name: 'FunctionAppTerminated',
    properties: {
      uptime: uptime,
      timestamp: new Date().toISOString()
    }
  });

  // Flush Application Insights data
  await new Promise((resolve) => client.flush({ callback: resolve }));
});

Le premier argument du gestionnaire de hooks est un objet de contexte spécifique à ce type de hook.

L’objet AppStartContext possède la propriété suivante :

Propriété Descriptif
hookData L’emplacement recommandé pour stocker et partager des données entre des hooks dans la même étendue. Utilisez un nom de propriété unique pour éviter tout conflit avec les données d’autres hooks.

L’objet AppTerminateContext possède la propriété suivante :

Propriété Descriptif
hookData L’emplacement recommandé pour stocker et partager des données entre des hooks dans la même étendue. Utilisez un nom de propriété unique pour éviter tout conflit avec les données des autres hooks.

Meilleures pratiques en matière de crochets

Lorsque vous utilisez des hooks dans vos Azure Functions, considérez ces bonnes pratiques :

Considérations relatives aux performances

  • Limitez au maximum le temps d’exécution du hook afin d’éviter d’affecter les performances de la fonction.
  • Utilisez des opérations asynchrones lorsque possible pour éviter le blocage.
  • Tenez compte du surcoût des hooks lors du traitement d’un fort volume de requêtes.

Gestion des erreurs

  • Incluez toujours une gestion appropriée des erreurs dans vos hooks.
  • Ne laissez pas les défaillances de crochet causer des défaillances fonctionnelles sauf si c’est absolument nécessaire.
  • Consigner correctement les erreurs liées aux hooks pour le débogage.

Partage des données

  • Utilisez hookData pour partager des informations entre les hooks de pré- et post-invocation.
  • Utilisez des noms de propriétés uniques pour éviter les conflits avec d’autres hooks.
  • Nettoyez les données associées aux hooks lorsqu’elles ne sont plus nécessaires afin d’éviter les fuites de mémoire.

Filtrage

  • Utilisez un filtrage de type de déclencheur pour vous assurer que les crochets ne fonctionnent que pour les fonctions pertinentes.
  • Soyez précis avec vos filtres pour optimiser la performance.

Mise à l’échelle et accès concurrentiel

Par défaut, Azure Functions surveille automatiquement la charge sur votre application et crée davantage d’instances d’hôte pour Node.js si nécessaire. Azure Functions utilise des seuils intégrés (non configurables par l’utilisateur) pour différents types de déclencheurs afin de décider quand ajouter des instances, comme l’âge des messages et la taille de la file d’attente pour QueueTrigger. Pour plus d’informations, consultez Fonctionnement des plans Consommation et Premium.

Ce comportement de mise à l’échelle est suffisant pour de nombreuses applications Node.js. Pour les applications utilisant le processeur de manière intensive, vous pouvez améliorer encore plus les performances en utilisant plusieurs processus Worker de langage. Vous pouvez augmenter le nombre de processus Worker par hôte de la valeur par défaut 1 jusqu’à un maximum de 10 à l’aide du paramètre d’application FUNCTIONS_WORKER_PROCESS_COUNT. Azure Functions tente ensuite de distribuer uniformément des appels de fonction simultanés entre ces travailleurs. Ce comportement réduit la probabilité qu’une fonction gourmande en ressources CPU bloque l’exécution des autres fonctions. Le paramètre s’applique à chaque hôte qui Azure Functions crée lors du scale-out de votre application pour répondre à la demande.

Avertissement

Utilisez le paramètre FUNCTIONS_WORKER_PROCESS_COUNT avec précaution. Plusieurs processus s’exécutant dans la même instance peuvent entraîner un comportement imprévisible et augmenter les temps de chargement des fonctions. Si vous utilisez ce paramètre, lancer depuis un fichier package peut compenser ces inconvénients.

Version de nœud

Vous pouvez voir la version que le runtime utilise en journalisant process.version depuis n’importe quelle fonction. Consultez supported versions pour la liste des versions Node.js prises en charge par chaque modèle de programmation.

Définition de la version de Node

La façon dont vous mettez à niveau votre version Node.js dépend du système d’exploitation sur lequel votre application de fonction s’exécute.

Quand il tourne sur Windows, définissez la version Node.js en utilisant le paramètre de l’applicationWEBSITE_NODE_DEFAULT_VERSION. Mettez à jour ce paramètre soit en utilisant l’interface Azure CLI, soit via le portail Azure.

Pour plus d’informations sur les versions Node.js disponibles, consultez Versions prises en charge.

Avant de mettre à niveau votre version de Node.js, vérifiez que votre application de fonction s’exécute sur la dernière version du runtime Azure Functions. Si vous devez mettre à niveau votre version du runtime, consultez Migrate apps from Azure Functions version 3.x to version 4.x.

Exécutez la commande Azure CLI az functionapp config appsettings set pour mettre à jour la version Node.js de votre application de fonction s’exécutant sur Windows :

az functionapp config appsettings set  --settings WEBSITE_NODE_DEFAULT_VERSION=~22 \
 --name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>

Cette commande règle le paramètre de l’applicationWEBSITE_NODE_DEFAULT_VERSION sur la version ~22LTS prise en charge.

Après avoir effectué des modifications, votre application de fonctions redémarre. Pour en savoir plus sur la prise en charge de Functions pour Node.js, consultez Stratégie de support du runtime de langage.

Variables d'environnement

Utilisez des variables d’environnement pour gérer les secrets opérationnels, tels que les chaînes de connexion, les clés et les points de terminaison. Utilisez-les aussi pour les paramètres environnementaux, comme le profilage des variables. Ajoutez des variables d’environnement dans vos environnements locaux et cloud, et accédez-y depuis le code de votre fonction via process.env.

L’exemple suivant journalise la variable d’environnement WEBSITE_SITE_NAME :

module.exports = async function (context) {
  context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
};
async function timerTrigger1(myTimer, context) {
  context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
}

Dans un environnement de développement local

Lorsque vous effectuez une exécution locale, votre projet Functions comprend un local.settings.json fichier dans lequel vous stockez vos variables d’environnement dans l’objet Values.

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "CUSTOM_ENV_VAR_1": "hello",
    "CUSTOM_ENV_VAR_2": "world"
  }
}

Dans l'environnement cloud Azure

Lorsque vous exécutez Azure, l’application de fonction vous permet de définir et d’utiliser les paramètres Application, tels que les chaînes de connexion de service, et expose ces paramètres en tant que variables d’environnement pendant l’exécution.

Plusieurs méthodes sont possibles pour ajouter, mettre à jour et supprimer des paramètres d’une application de fonction :

Les changements apportés aux paramètres d’application de fonction nécessitent le redémarrage de votre application de fonction.

Variables d’environnement worker

Node.js possède plusieurs variables d’environnement Fonctions qui lui sont propres :

languageWorkers__node__arguments

Utilisez ce paramètre pour spécifier des arguments personnalisés lors du lancement de votre processus Node.js. Le plus souvent, on l’utilise localement pour lancer le worker en mode débogage, mais on peut aussi l’utiliser dans Azure si on a besoin d’arguments personnalisés.

Avertissement

Si possible, évitez d’utiliser languageWorkers__node__arguments dans Azure car cela peut nuire aux heures de démarrage à froid. Plutôt que d’utiliser des instances préchauffées, l’environnement d’exécution doit démarrer une nouvelle instance à partir de zéro à l’aide de vos arguments personnalisés.

journalisationlogLevelWorker

Utilisez ce paramètre pour ajuster le niveau de journal par défaut pour les logs de travail spécifiques à Node.js. Par défaut, seuls les journaux d’avertissement ou d’erreur sont affichés, mais vous pouvez le définir sur information ou sur debug pour faciliter le diagnostic des problèmes liés au worker Node.js. Pour plus d’informations, consultez Configuration des niveaux de journal.

Modules ECMAScript (préversion)

Remarque

Les modules ECMAScript sont actuellement une fonctionnalité en préversion dans Azure Functions pour Node.js 14 ou version ultérieure.

Les modules ECMAScript (modules ES) sont le nouveau système de modules standard officiel pour Node.js. Jusqu’à présent, les exemples de code de cet article utilisent la syntaxe CommonJS. Lorsque Azure Functions exécute en Node.js 14 ou plus, vous pouvez choisir d’écrire vos fonctions en utilisant la syntaxe des modules ES.

Pour utiliser les modules ES dans une fonction, modifiez son nom de fichier pour qu’elle utilise une extension .mjs. L’exemple de fichier index.mjs suivant est une fonction déclenchée par HTTP qui utilise la syntaxe des modules ES pour importer la bibliothèque uuid et renvoyer une valeur.

import { v4 as uuidv4 } from "uuid";

async function httpTrigger1(context, request) {
  context.res.body = uuidv4();
}

export default httpTrigger;
import { v4 as uuidv4 } from "uuid";

async function httpTrigger1(request, context) {
  return { body: uuidv4() };
}

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

Configurer le point d’entrée de la fonction

Utilisez les function.json propriétés scriptFile et entryPoint pour définir l’emplacement et le nom de votre fonction exportée. Quand vous utilisez TypeScript, vous avez besoin de la scriptFile propriété et elle doit pointer vers le JavaScript compilé.

Utilisation de scriptFile

Par défaut, une fonction JavaScript s’exécute à partir index.jsde . Ce fichier partage le même répertoire parent que le fichier correspondant function.json .

Utilisez-le scriptFile pour organiser la structure de vos dossiers. L’exemple suivant montre une façon de configurer vos dossiers :

<project_root>/
 | - node_modules/
 | - myFirstFunction/
 | | - function.json
 | - lib/
 | | - sayHello.js
 | - host.json
 | - package.json

Le function.json fichier pour myFirstFunction devrait inclure une scriptFile propriété qui pointe vers le fichier avec la fonction exportée à exécuter.

{
  "scriptFile": "../lib/sayHello.js",
  "bindings": [
    ...
  ]
}

Utilisation de entryPoint

Dans le modèle v3, vous devez exporter une fonction en utilisant module.exports afin que la fonction puisse être trouvée et exécutée. Par défaut, la fonction qui s’exécute lorsqu’elle est déclenchée est la seule exportation de ce fichier. Il peut aussi s’agir de l’exportation nommée run ou de l’exportation nommée index. L’exemple suivant définit entryPoint dans function.json sur une valeur personnalisée, « logHello » :

{
  "entryPoint": "logHello",
  "bindings": [
    ...
  ]
}
async function logHello(context) {
  context.log("Hello, world!");
}

module.exports = { logHello };

Recommandations

Cette section décrit plusieurs schémas marquants pour Node.js applications que vous devriez suivre.

Choisir des plans App Service à processeur virtuel unique

Lorsque vous créez une application fonctionnelle utilisant le plan App Service, choisissez un forfait à un seul vCPU plutôt qu’un forfait avec plusieurs vCPU. Aujourd’hui, Functions exécute Node.js fonctions plus efficacement sur des machines virtuelles à un seul vCPU, et utiliser des machines virtuelles plus grandes n’apporte pas les améliorations de performance attendues. Si nécessaire, vous pouvez augmenter la capacité en ajoutant d’autres instances de machine virtuelle à vCPU unique, ou activer la mise à l’échelle automatique. Pour plus d’informations, consultez Mettre à l’échelle le nombre d’instances manuellement ou automatiquement.

Effectuer l’exécution à partir d’un fichier de package

Lorsque vous développez Azure Functions dans le modèle d’hébergement serverless, les démarrages à froid sont une réalité. Démarrage à froid fait référence à la première fois que votre application de fonction démarre après une période d’inactivité, prenant plus de temps au démarrage. En particulier pour les applications Node.js avec de grandes arborescences de dépendances, le démarrage à froid peut prendre un temps considérable. Pour accélérer le processus de démarrage à froid, exécutez vos fonctions en tant que fichier de package lorsque cela est possible. De nombreuses méthodes de déploiement utilisent ce modèle par défaut, mais si vous rencontrez de gros démarrages à froid, vérifiez que vous fonctionnez ainsi.

Utiliser async et await

Lorsque vous écrivez Azure Functions dans Node.js, écrivez du code en utilisant les async mots-clés etawait. Écrire du code en utilisant async et await plutôt que des fonctions de rappel ou .then et .catch avec les promesses vous aide à éviter deux problèmes courants :

  • Levée d’exceptions non interceptées qui bloquent le processus Node.js, affectant ainsi potentiellement l’exécution d’autres fonctions.
  • Comportement inattendu, comme des journaux manquants dans context.log, en raison d’appels asynchrones inattendus.

Dans l’exemple suivant, la méthode asynchrone fs.readFile est appelée avec une fonction de rappel d’erreur en premier comme second paramètre. Ce code entraîne les deux problèmes précédemment mentionnés. Une exception qui n’est pas interceptée explicitement dans l’étendue appropriée peut planter l’ensemble du processus (problème n°1). Un retour sans s’assurer que le rappel se termine signifie que la réponse HTTP a parfois un corps vide (problème #2).

// DO NOT USE THIS CODE
const { 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 process
                throw err;
            }
            fileData = data;
        });
        // BUG #2: fileData is not guaranteed to be set before the invocation ends
        return { body: fileData };
    },
});

Dans l’exemple suivant, la méthode asynchrone fs.readFile est appelée avec une fonction de rappel d’erreur en premier comme second paramètre. Ce code cause les deux problèmes mentionnés précédemment. Une exception qui n’est pas explicitement captée dans le bon champ de vision peut faire planter tout le processus (problème #1). Appeler la méthode obsolète context.done() en dehors du champ du rappel peut signaler que la fonction est terminée avant que le fichier ne soit lu (problème #2). Dans cet exemple, un appel context.done() trop tôt entraîne des entrées de journal manquantes avec Data from file:.

// NOT RECOMMENDED PATTERN
const 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 process
      throw 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();
};

Utilisez les async mots-clés et await pour éviter ces deux problèmes. La plupart des API de l’écosystème Node.js supportent désormais des promesses sous une forme ou une autre. Par exemple, à partir de la version 14, Node.js fournit une fs/promises API pour remplacer l’API fs de rappel.

Dans l’exemple suivant, les exceptions non prises en charge levées pendant l’exécution de la fonction entraînent uniquement un échec de l’appel individuel qui a levé l’exception. Le mot clé await implique que les étapes après readFile ne s’exécutent que lorsqu’elle est terminée.

// Recommended pattern
const { app } = require('@azure/functions');
const fs = require('fs/promises');

app.http('httpTriggerGoodAsync', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        try {
            const fileData = await fs.readFile('./helloWorld.txt');
            return { body: fileData };
        } catch (err) {
            context.error(err);
            // This rethrown exception will only fail the individual invocation, instead of crashing the whole process
            throw err;
        }
    },
});

Quand vous utilisez async et await, vous n’avez pas besoin d’appeler la fonction de rappel context.done().

// Recommended pattern
const fs = require("fs/promises");

module.exports = async function (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 invocation
    throw err;
  }
  context.log(`Data from file: ${data}`);
};

Dépanner

Consultez le Guide de dépannage de Node.js.

Étapes suivantes

Pour plus d’informations, consultez les ressources suivantes :