Guide du développeur Node.js sur Azure Functions
Ce guide est une introduction au développement d’Azure Functions à l’aide de JavaScript ou TypeScript. L’article suppose que vous avez déjà lu le Guide de développement Azure Functions.
Important
Le contenu de cet article change en fonction de votre choix du modèle de programmation Node.js dans le sélecteur en haut de cette page. La version que vous choisissez doit correspondre à la version du package npm @azure/functions
que vous utilisez dans votre application. Si ce package n’est pas répertorié dans votre package.json
, la valeur par défaut est v3. En savoir plus sur les différences entre v3 et v4 dans le guide de migration.
En tant que développeur Node.js, vous pouvez également être intéressé par l’un des articles suivants :
Prise en main | Concepts | Apprentissage guidé |
---|---|---|
À propos de l’installation
- Le modèle de programmation Node.js ne doit pas être confondu avec le runtime Azure Functions :
- Modèle de programmation : définit la façon dont vous créez votre code et est spécifique à JavaScript et TypeScript.
- Runtime : définit le comportement sous-jacent de Azure Functions et est partagé entre tous les langages.
- La version du modèle de programmation est strictement liée à celle du package npm
@azure/functions
. Cela est versionné indépendamment du runtime. Le runtime et le modèle de programmation utilisent tous les deux le nombre 4 comme dernière version majeure, mais cela est une coïncidence. - Vous ne pouvez pas combiner les modèles de programmation v3 et v4 dans la même application de fonction. Dès que vous inscrivez une fonction v4 dans votre application, toutes les fonctions v3 inscrites dans des fichiers function.json sont ignorées.
Versions prises en charge
Le tableau suivant montre chaque version du modèle de programmation Node.js ainsi que ses versions prises en charge du runtime et de l'Node.js Azure Functions.
Version du modèle de programmation | Niveau de prise en charge | Version du runtime Functions | Version de Node.js | Description |
---|---|---|---|---|
4.x | GA | 4.25+ | 20.x, 18.x | Prend en charge une structure de fichiers flexible et une approche centrée sur le code pour les déclencheurs et les liaisons. |
3.x | GA | 4.x | 20.x, 18.x, 16.x, 14.x | Nécessite une structure de fichiers spécifique avec vos déclencheurs et liaisons déclarés dans un fichier « function.json » |
2.x | n/a | 3.x | 14.x, 12.x, 10.x | A atteint la fin de la prise en charge le 13 décembre 2022. Pour plus d’informations, consultez Versions de Functions. |
1.x | n/a | 2.x | 10.x, 8.x | A atteint la fin de la prise en charge le 13 décembre 2022. Pour plus d’informations, consultez Versions de Functions. |
Structure de dossiers
La structure de dossiers requise pour un projet JavaScript est similaire à 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 Paramètres Visual Studio Code.
- 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 des fichiers qui ne devraient pas être publiés sur Azure. En règle générale, ce fichier contient .vscode/ pour ignorer le paramètre de votre éditeur, test/ pour ignorer les cas de test et local.settings.json pour empêcher la publication des paramètres de l’application locale.
- 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é sur Azure. Pour en savoir plus, consultez la section local.settings.file.
- package.json : contient des options de configuration telles qu’une liste de dépendances de package, le point d’entrée principal et des scripts.
La structure de dossiers recommandée d’un projet JavaScript se présente comme 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 Paramètres Visual Studio Code.
- 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 des fichiers qui ne devraient pas être publiés sur Azure. En règle générale, ce fichier contient .vscode/ pour ignorer le paramètre de votre éditeur, test/ pour ignorer les cas de test et local.settings.json pour empêcher la publication des paramètres de l’application locale.
- 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é sur Azure. Pour en savoir plus, consultez la section local.settings.file.
- package.json : contient des options de configuration telles qu’une liste de dépendances de package, le point d’entrée principal et des scripts.
Inscription d’une fonction
Le modèle v3 inscrit une fonction en se basant sur l’existence de deux fichiers. Tout d’abord, vous avez besoin d’un fichier function.json
situé dans un dossier se trouvant un niveau sous la racine de votre application. Ensuite, vous avez besoin d’un fichier JavaScript qui exporte votre fonction. Par défaut, le modèle recherche un fichier index.js
se trouvant dans le même dossier que votre fichier function.json
. Si vous utilisez TypeScript, vous devez utiliser la propriété scriptFile
dans function.json
pour pointer vers le fichier JavaScript compilé. Pour personnaliser l’emplacement de fichier ou le nom d’exportation de votre fonction, consultez la configuration du point d’entrée de votre fonction.
La fonction que vous exportez doit toujours être déclarée en tant que async function
dans le modèle v3. Vous pouvez exporter une fonction synchrone, mais vous devez ensuite appeler context.done()
pour signaler que votre fonction est terminée, ce qui est déprécié et non recommandé.
Un appel context
passé à votre fonction en tant que premier argument et vos entrées sont passées en tant qu’arguments restants.
L’exemple suivant est une fonction simple qui enregistre dans un journal qu’elle a été déclenchée et répond avec Hello, world!
:
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"authLevel": "anonymous",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, request) {
context.log('Http function was triggered.');
context.res = { body: 'Hello, world!' };
};
Le modèle de programmation charge vos fonctions en fonction du champ main
dans votre package.json
. Vous pouvez définir le champ main
sur un fichier unique ou plusieurs fichiers à l’aide d’un modèle Glob. Le tableau suivant présente des exemples de valeurs pour le champ main
:
Exemple | Description |
---|---|
src/index.js |
Inscrivez des fonctions à partir d’un seul fichier racine. |
src/functions/*.js |
Inscrivez chaque fonction à partir de son propre fichier. |
src/{index.js,functions/*.js} |
Une combinaison dans laquelle vous inscrivez chaque fonction à partir de son propre fichier, mais vous disposez toujours d’un fichier racine pour le code général au niveau de l’application. |
Pour inscrire une fonction, vous devez importer l’objet app
à partir du module npm @azure/functions
et appeler la méthode spécifique à votre type de déclencheur. Le premier argument lors de l’inscription d’une fonction est le nom de la fonction. Le deuxième argument est un objet options
spécifiant la configuration de votre déclencheur, de votre gestionnaire et de toutes les autres entrées ou sorties. Dans les cas où la configuration du déclencheur n’est pas nécessaire, vous pouvez passer le gestionnaire directement comme deuxième argument plutôt qu’un objet options
.
L’inscription d’une fonction peut être effectuée à partir de n’importe quel fichier de votre projet, à condition que ce fichier soit chargé (directement ou indirectement) en fonction du champ main
dans votre fichier package.json
. La fonction doit être inscrite dans une étendue globale, car vous ne pouvez pas inscrire les fonctions une fois que les exécutions ont commencé.
L’exemple suivant est une fonction simple qui enregistre dans un journal qu’elle a été déclenchée et répond avec Hello, world!
:
const { app } = require('@azure/functions');
app.http('helloWorld1', {
methods: ['POST', 'GET'],
handler: async (request, context) => {
context.log('Http function was triggered.');
return { body: 'Hello, world!' };
}
});
Entrées et sorties
Votre fonction doit avoir exactement une entrée primaire appelée déclencheur. Il peut également avoir des entrées et/ou des sorties secondaires. Les entrées et sorties, qui sont également appelées liaisons, sont configurées dans vos fichiers function.json
.
Entrées
Les entrées sont des liaisons dont la valeur direction
est définie sur in
. La principale différence entre un déclencheur et une entrée secondaire est que le type
d’un déclencheur se termine par Trigger
; par exemple, le type blobTrigger
par rapport au type blob
. La plupart des fonctions utilisent uniquement un déclencheur, et peu de types d’entrée secondaires sont pris en charge.
Les entrées sont accessibles de plusieurs façons :
[Recommandé] En tant qu’arguments passés à votre fonction : utilisez les arguments dans le même ordre que celui dans lequel ils sont définis dans
function.json
. La propriéténame
définie dansfunction.json
n’a pas besoin de correspondre au nom de votre argument, même si cela est recommandé par souci d’organisation.module.exports = async function (context, myTrigger, myInput, myOtherInput) { ... };
En tant que propriétés de
context.bindings
: utilisez la clé correspondant à la propriéténame
définie dansfunction.json
.module.exports = async function (context) { context.log("This is myTrigger: " + context.bindings.myTrigger); context.log("This is myInput: " + context.bindings.myInput); context.log("This is myOtherInput: " + context.bindings.myOtherInput); };
Sorties
Les sorties sont des liaisons dont la valeur direction
est définie sur out
et qui peuvent être définies de plusieurs façons :
[Recommandé en cas de sortie unique] Retourner la valeur directement : si vous utilisez une fonction asynchrone, vous pouvez retourner la valeur directement. Vous devez remplacer la propriété
name
de la liaison de sortie par$return
dansfunction.json
, comme dans l’exemple suivant :{ "name": "$return", "type": "http", "direction": "out" }
module.exports = async function (context, request) { return { body: "Hello, world!" }; }
[Recommandé en cas de sorties multiples] Retourner un objet contenant toutes les sorties : si vous utilisez une fonction asynchrone, vous pouvez retourner un objet avec une propriété correspondant au nom de chaque liaison dans votre fichier
function.json
. L’exemple suivant utilise des liaisons de sortie nommées « httpResponse » et « queueOutput » :{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; return { httpResponse: { body: message }, queueOutput: message }; };
Définir des valeurs sur
context.bindings
: si vous n’utilisez pas une fonction asynchrone ou si vous ne voulez pas utiliser les options précédentes, vous pouvez définir des valeurs directement surcontext.bindings
, où la clé correspond au nom de la liaison. L’exemple suivant utilise des liaisons de sortie nommées « httpResponse » et « queueOutput » :{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; context.bindings.httpResponse = { body: message }; context.bindings.queueOutput = message; };
Type de données de liaisons
Vous pouvez utiliser la propriété dataType
sur une liaison d’entrée pour changer le type de votre entrée, mais elle présente certaines limitations :
- Dans Node.js, seuls
string
etbinary
sont pris en charge (stream
ne l’est pas) - Pour les entrées HTTP, la propriété
dataType
est ignorée. Utilisez à la place des propriétés sur l’objetrequest
pour obtenir le corps dans le format que vous souhaitez. Pour plus d’informations, consultez Requête HTTP.
Dans l’exemple suivant d’un déclencheur de file d’attente de stockage, le type par défaut de myQueueItem
est string
(chaîne), mais si vous définissez dataType
sur binary
, le type devient un Buffer
(mémoire tampon) Node.js.
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "helloworldqueue",
"connection": "storage_APPSETTING",
"dataType": "binary"
}
const { Buffer } = require('node:buffer');
module.exports = async function (context, myQueueItem) {
if (typeof myQueueItem === 'string') {
context.log('myQueueItem is a string');
} else if (Buffer.isBuffer(myQueueItem)) {
context.log('myQueueItem is a buffer');
}
};
Votre fonction doit avoir exactement une entrée primaire appelée déclencheur. Il peut également avoir des entrées secondaires, une sortie primaire appelée sortie de retour et/ou des sorties secondaires. Les entrées et les sorties sont également appelées liaisons en dehors du contexte du modèle de programmation Node.js. Avant la version 4 du modèle, ces liaisons étaient configurées dans des fichiers function.json
.
Entrée du déclencheur
Le déclencheur est la seule entrée ou sortie requise. Pour la plupart des types de déclencheurs, vous inscrivez une fonction à l’aide d’une méthode sur l’objet app
nommé d’après le type de déclencheur. Vous pouvez spécifier une configuration spécifique au déclencheur directement sur l’argument options
. Par exemple, un déclencheur HTTP vous permet de spécifier un itinéraire. Pendant l’exécution, la valeur correspondant à ce déclencheur est transmise en tant que premier argument à votre gestionnaire.
const { app } = require('@azure/functions');
app.http('helloWorld1', {
route: 'hello/world',
handler: async (request, context) => {
...
}
});
Sortie de retour
La sortie de retour est facultative et, dans certains cas, configurée par défaut. Par exemple, un déclencheur HTTP inscrit avec app.http
est configuré pour retourner automatiquement une sortie de réponse HTTP. Pour la plupart des types de sortie, vous spécifiez la configuration de retour sur l’argument options
à l’aide de l’objet output
exporté à partir du module @azure/functions
. Pendant l’exécution, vous définissez cette sortie en la retournant à partir de votre gestionnaire.
L’exemple suivant utilise un déclencheur de minuteur et une sortie de file d’attente de stockage :
const { app, output } = require('@azure/functions');
app.timer('timerTrigger1', {
schedule: '0 */5 * * * *',
return: output.storageQueue({
connection: 'storage_APPSETTING',
...
}),
handler: (myTimer, context) => {
return { hello: 'world' }
}
});
Entrées et sorties supplémentaires
En plus du déclencheur et du retour, vous pouvez spécifier des entrées ou des sorties supplémentaires dans l’argument options
lors de l’inscription d’une fonction. Les objets input
et output
exportés à partir du module @azure/functions
fournissent des méthodes spécifiques au type pour aider à construire la configuration. Pendant l’exécution, vous obtenez ou définissez les valeurs avec context.extraInputs.get
ou context.extraOutputs.set
, en passant l’objet de configuration d’origine comme premier argument.
L’exemple suivant est une fonction déclenchée par une file d’attente de stockage, avec une entrée d’objet blob de stockage supplémentaire qui est copiée dans une sortie d’objet blob de stockage supplémentaire. Le message de file d’attente doit être le nom d’un fichier et remplace {queueTrigger}
comme nom d’objet blob à copier, à l’aide d’une expression de liaison.
const { app, input, output } = require('@azure/functions');
const blobInput = input.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}',
});
const blobOutput = output.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}-copy',
});
app.storageQueue('copyBlob1', {
queueName: 'copyblobqueue',
connection: 'storage_APPSETTING',
extraInputs: [blobInput],
extraOutputs: [blobOutput],
handler: (queueItem, context) => {
const blobInputValue = context.extraInputs.get(blobInput);
context.extraOutputs.set(blobOutput, blobInputValue);
}
});
Entrées et sorties génériques
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!` };
}
});
Contexte d’appel
Un objet context
d’appel, utilisé pour lire des entrées, définir des sorties, écrire dans des journaux et lire diverses métadonnées, est passé à chaque appel de votre fonction. Dans le modèle v3, l’objet de contexte est toujours le premier argument passé à votre gestionnaire.
L’objet context
dispose des propriétés suivantes :
Propriété | Description |
---|---|
invocationId |
ID de l’appel de fonction en cours. |
executionContext |
Consultez Contexte d’exécution. |
bindings |
Consultez Liaisons. |
bindingData |
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 . |
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é | Description |
---|---|
invocationId |
ID de l’appel de fonction en cours. |
functionName |
Nom de la fonction qui est appelée. 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é | Description |
---|---|
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
L’objet context.bindings
est utilisé pour lire des entrées ou définir des sorties. L’exemple suivant est un déclencheur de file d’attente de stockage, qui utilise context.bindings
pour copier une entrée d’objet blob de stockage dans une sortie d’objet 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 que les fonctions asynchrones soient prises en charge, vous signaliez que l’exécution de votre fonction était terminée en appelant context.done()
:
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
Maintenant, il est recommandé de supprimer l’appel à context.done()
et de marquer votre fonction comme asynchrone afin qu’elle retourne une promesse, même si vous n’attendez (await
) rien. 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")
};
Un objet context
d’appel, avec des informations sur votre appel et les méthodes utilisées pour la journalisation, est passé à chaque appel de votre fonction. Dans le modèle v4, l’objet context
est généralement le deuxième argument passé à votre gestionnaire.
La classe InvocationContext
a les propriétés suivantes:
Propriété | Description |
---|---|
invocationId |
ID 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’inscription de la fonction, une fois qu’elles ont été validées et avec les valeurs par défaut spécifiées explicitement. |
Contexte de nouvelle tentative
L’objet retryContext
dispose des propriétés suivantes :
Propriété | Description |
---|---|
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, il est recommandé d’utiliser context.log()
pour écrire des journaux. Azure Functions s’intègre à Azure Application Insights pour mieux capturer les journaux de vos applications de fonction. Application Insights, qui fait partie de Azure Monitor, fournit des ressources pour la collecte, le rendu visuel, ainsi que l’analyse des journaux des applications et de vos sorties de trace. Pour en savoir plus, consultez Surveiller l’exécution des fonctions Azure.
Notes
Si vous utilisez l’autre méthode Node.js console.log
, ces journaux sont suivis au niveau de l’application et ne sont associés à aucune fonction spécifique. Il est vivement recommandé d’utiliser context
pour la journalisation plutôt que console
pour 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 journalisation
Outre la méthode context.log
par défaut, les méthodes suivantes sont disponibles pour vous permettre d’écrire des journaux à des niveaux spécifiques :
Méthode | Description |
---|---|
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 | Description |
---|---|
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
Azure Functions vous permet de définir le niveau de seuil à utiliser lors du suivi et de l’affichage de 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 appliqué à toutes les fonctions, ou un seuil pour chaque fonction individuelle. Pour plus d’informations, consultez Comment configurer la surveillance de 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, vous pouvez plutôt utiliser le Kit de développement logiciel (SDK) node.js d’Application Insights pour envoyer des données personnalisées vers votre instance Application Insights.
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 paramètre permet de mettre en corrélation tous les journaux générés automatiquement et personnalisés pour un appel de fonction donné.
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
Les requêtes sont accessibles de plusieurs façons :
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 façon que toute liaison non HTTP. Le nom de liaison dans
function.json
doit correspondre à la clé surcontext.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 | Description |
---|---|---|
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. Il est recommandé d’utiliser plutôt request.getHeader('header-name') , qui ne respecte pas la casse. |
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. |
La requête est accessible en tant que premier argument de votre gestionnaire pour une fonction déclenchée via 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 | Description |
---|---|---|
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 requête ou d’une réponse, vous pouvez utiliser les méthodes suivantes :
Méthode | Type de retour |
---|---|
arrayBuffer() |
Promise<ArrayBuffer> |
blob() |
Promise<Blob> |
formData() |
Promise<FormData> |
json() |
Promise<unknown> |
text() |
Promise<string> |
Notes
Les fonctions du corps ne peuvent être exécutées qu’une seule fois ; les appels suivants seront résolus avec des chaînes/ArrayBuffers vides.
Réponse HTTP
La réponse peut être définie de plusieurs manières :
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 votrefunction.json
, vous pouvez retourner la réponse directement au lieu de la définir surcontext
.{ "type": "http", "direction": "out", "name": "$return" }
module.exports = async function (context, request) { return { body: `Hello, world!` };
Définir la liaisons de sortie nommée : cette option fonctionne de la même façon que toute liaison non HTTP. Le nom de liaison dans
function.json
doit correspondre à la clé surcontext.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!` };
Appeler
context.res.send()
: Cette option est dépréciée. Elle appellecontext.done()
implicitement et ne peut pas être utilisée 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 | Description |
---|---|---|
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 de statut 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 | Description |
---|---|
status() |
Définit l’état. |
setHeader() |
Définit un champ d’en-tête. REMARQUE : res.set() et res.header() sont également pris en charge et font la même chose. |
getHeader() |
Permet d’obtenir un champ d’en-tête. REMARQUE : res.get() est également pris en charge et fait la même chose. |
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 fait la même chose. |
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. |
La réponse peut être définie de plusieurs manières :
En tant qu’interface simple avec le type
HttpResponseInit
: cette option est le moyen le plus concis de retourner des réponses.return { body: `Hello, world!` };
Une interface
HttpResponseInit
possède les propriétés suivantes :Propriété Type Description body
BodyInit
(facultatif)Corps de la réponse HTTP sous la forme de ArrayBuffer
,AsyncIterable<Uint8Array>
,Blob
,FormData
,Iterable<Uint8Array>
,NodeJS.ArrayBufferView
,URLSearchParams
,null
oustring
.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 de statut 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 facultatifHttpResponseInit
comme argument de son constructeur et possède les propriétés suivantes :Propriété Type Description status
number
Code de statut 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 a déjà été 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
- Le
@azure/functions
package npm version 4.3.0 ou ultérieure. - Runtime Azure Functions version 4.28 ou ultérieure.
- Azure Functions Core Tools version 4.0.5530 ou ultérieure, qui contient la version d’exécution correcte.
Activer les flux
Procédez comme suit pour activer les flux HTTP dans votre application de fonction dans Azure et dans vos projets locaux :
Si vous envisagez de diffuser en continu de grandes quantités de données, modifiez le paramètre de
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
dans Azure. La taille maximale de corps par défaut autorisée est104857600
, ce qui limite vos demandes à une taille d’environ 100 Mo.Pour le développement local, ajoutez également
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
au fichier local.settings.json.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
Cet exemple montre une fonction déclenchée par HTTP qui reçoit des données via une requête HTTP POST, et la fonction diffuse 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!' };
},
});
Cet exemple montre une fonction déclenchée par HTTP qui diffuse le contenu d’un fichier en tant que 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 un exemple d’application prête à l’emploi utilisant des flux, consultez cet exemple sur GitHub.
Considérations relatives au flux de données
- Utilisez
request.body
pour obtenir le maximum d’avantages de l’utilisation de flux. Vous pouvez toujours continuer à utiliser des méthodes commerequest.text()
, qui retournent toujours le corps sous forme de chaîne.
Hooks
Les hooks ne sont pas pris en charge dans le modèle v3. 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 d’Azure Functions. Les hooks sont exécutés dans l’ordre dans lequel ils sont inscrits et peuvent être inscrits à partir de n’importe quel fichier de votre application. Il existe actuellement deux étendues de hooks, de niveau « application » et de niveau « appel ».
Crochets d’appel
Les crochets d’appel sont exécutés une fois par appel de votre fonction, soit avant, dans un hook preInvocation
, soit après, dans un hook postInvocation
. Par défaut, votre hook s’exécute pour tous les types de déclencheurs, mais vous pouvez également 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');
app.hook.preInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`preInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
app.hook.postInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`postInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
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é | Description |
---|---|
inputs |
Les arguments passés à l’appel. |
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. Vous devez utiliser un nom de propriété unique afin qu’il ne soit pas en conflit avec les données d’autres hooks. |
L’objet PostInvocationContext
dispose des propriétés suivantes :
Propriété | Description |
---|---|
inputs |
Les arguments passés à l’appel. |
result |
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. Vous devez utiliser un nom de propriété unique afin qu’il ne soit pas en conflit avec les données d’autres hooks. |
Hooks d’application
Les hooks d’application sont exécutés une fois par instance de votre application, soit au démarrage dans un hook appStart
, soit lors de l’arrêt dans un hook appTerminate
. 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 contextuelle en dehors d’un appel. 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');
app.hook.appStart((context) => {
// add your logic here
});
app.hook.appTerminate((context) => {
// add your logic here
});
Le premier argument du gestionnaire de hooks est un objet de contexte spécifique à ce type de hook.
L’objet AppStartContext
dispose des propriétés suivantes :
Propriété | Description |
---|---|
hookData |
L’emplacement recommandé pour stocker et partager des données entre des hooks dans la même étendue. Vous devez utiliser un nom de propriété unique afin qu’il ne soit pas en conflit avec les données d’autres hooks. |
L’objet AppTerminateContext
dispose des propriétés suivantes :
Propriété | Description |
---|---|
hookData |
L’emplacement recommandé pour stocker et partager des données entre des hooks dans la même étendue. Vous devez utiliser un nom de propriété unique afin qu’il ne soit pas en conflit avec les données d’autres hooks. |
Mise à l’échelle et accès concurrentiel
Par défaut, Azure Functions surveille automatiquement la charge dans votre application et crée des instances d’hôte supplémentaires 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’ancienneté 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 essaie ensuite de distribuer uniformément les appels de fonction simultanés à ces différents Workers. 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 créé par Azure Functions lors de la mise à l’échelle 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, il est vivement recommandé de compenser ces inconvénients en effectuant l’exécution à partir d’un fichier de package.
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.
Lors de l’exécution sur Windows, la version Node.js est définie par le paramètre d’application WEBSITE_NODE_DEFAULT_VERSION
. Ce paramètre peut être mis à jour à l’aide d’Azure CLI ou dans le Portail Azure.
Pour plus d’informations sur les versions Node.js disponibles, consultez Versions prises en charge.
Avant de mettre à niveau votre version Node.js, assurez-vous 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 Migrer des applications de Azure Functions version 3.x vers la 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=~20 \
--name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>
Cela définit le paramètre d’application WEBSITE_NODE_DEFAULT_VERSION
la version LTS prise en charge de ~20
.
Une fois les modifications apportées, votre application de fonction 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
Les variables d’environnement peuvent être utiles pour les secrets opérationnels (chaînes de connexion, clés, points de terminaison, etc.) ou les paramètres environnementaux tels que les variables de profilage. Vous pouvez ajouter des variables d’environnement dans vos environnements locaux et cloud, et y accéder via process.env
dans le code de votre fonction.
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 un environnement cloud Azure
Lorsque vous effectuez une exécution dans Azure, l’application de fonction vous permet de définir et d’utiliser des paramètres d’application comme des chaînes de connexion de service, tout en exposant ces paramètres sous forme de 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
Il existe plusieurs variables d’environnement Functions spécifiques à Node.js :
languageWorkers__node__arguments
Ce paramètre vous permet de spécifier des arguments personnalisés lors du démarrage de votre processus Node.js. Il est le plus souvent utilisé localement pour démarrer le worker en mode débogage, mais peut également être utilisé dans Azure si vous avez besoin d’arguments personnalisés.
Avertissement
Si possible, évitez d’utiliser languageWorkers__node__arguments
dans Azure, car cela peut avoir un effet négatif sur les heures de démarrage à froid. Au lieu d’utiliser des workers chauffées au préalable, le runtime doit démarrer un nouveau worker à partir de zéro avec vos arguments personnalisés.
logging__logLevel__Worker
Ce paramètre ajuste le niveau de journal par défaut pour les journaux worker 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)
Notes
Comme les modules ECMAScript sont actuellement une fonctionnalité d’évaluation dans Node.js 14 et ultérieur Azure Functions.
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 vous exécutez Azure Functions dans Node.js 14 ou une version ultérieure, 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
Vous pouvez utiliser les propriétés function.json
scriptFile
et entryPoint
pour configurer l’emplacement et le nom de votre fonction exportée. La propriété scriptFile
est obligatoire quand vous utilisez TypeScript et doit pointer vers le code JavaScript compilé.
Utilisation de scriptFile
Par défaut, une fonction JavaScript est exécutée à partir de index.js
, fichier qui partage le même répertoire parent que son function.json
correspondant.
Vous pouvez utiliser la propriété scriptFile
pour obtenir une structure de dossiers semblable à l’exemple suivant :
<project_root>/
| - node_modules/
| - myFirstFunction/
| | - function.json
| - lib/
| | - sayHello.js
| - host.json
| - package.json
Le function.json
pour myFirstFunction
doit inclure une propriété scriptFile
qui pointe vers le fichier contenant la fonction exportée à exécuter.
{
"scriptFile": "../lib/sayHello.js",
"bindings": [
...
]
}
Utilisation de entryPoint
Dans le modèle v3, une fonction doit être exportée à l’aide de module.exports
afin qu’elle soit trouvée et exécutée. Par défaut, la fonction qui s’exécute quand elle est déclenchée est la seule exportation à partir de ce fichier, l’exportation nommée run
ou 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 };
Débogage local
Il est recommandé d’utiliser VS Code pour le débogage local, qui démarre automatiquement votre processus Node.js en mode débogage et effectue l’attachement au processus pour vous. Pour plus d’informations, consultez Exécuter la fonction localement.
Si vous utilisez un autre outil pour le débogage ou si vous souhaitez démarrer manuellement votre processus Node.js en mode débogage, ajoutez "languageWorkers__node__arguments": "--inspect"
sous Values
dans votre fichier local.settings.json. L’argument --inspect
indique à Node.js d’écouter un client de débogage sur le port 9229 par défaut. Pour plus d’informations, consultez le guide de débogage Node.js.
Recommandations
Cette section décrit plusieurs modèles impactants pour les applications Node.js que nous vous recommandons de suivre.
Choisir des plans App Service à processeur virtuel unique
Lorsque vous créez une application de fonction qui utilise le plan App Service, nous vous recommandons de sélectionner un plan à processeur virtuel unique plutôt qu’un plan à plusieurs processeurs virtuels. À l’heure actuelle, Functions exécute les fonctions Node.js plus efficacement sur des machines virtuelles à processeur virtuel unique. Le recours à de plus grandes machines virtuelles ne produit pas les améliorations de performances attendues. Le cas échéant, vous pouvez effectuer un scale-out manuellement en ajoutant des instances de machine virtuelle à processeur virtuel unique, ou vous pouvez 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 des fonctions 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 avez des démarrages à froid volumineux, vous devez vérifier pour vous assurer de l’exécuter de cette façon.
Utiliser un client statique unique
Lorsque vous utilisez un client spécifique du service dans une application Azure Functions, ne créez pas de nouveau client à chaque appel de fonction, car vous pouvez atteindre les limites de connexions. Créez plutôt un client statique unique dans l’étendue globale. Pour plus d’informations, consultez l’article relatif à la gestion des connexions dans Azure Functions.
Utiliser async
et await
Lors de l’écriture d’Azure Functions dans Node.js, vous devez écrire le code à l’aide des mots clés async
et await
. L’écriture de code à l’aide de async
et await
au lieu de rappels ou de .then
et .catch
avec Promises permet d’é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). Le retour sans s’assurer que le rappel se termine signifie que la réponse http aura parfois un corps vide (problème n° 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 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 appel à la méthode dépréciée context.done()
en dehors de l’étendue du rappel peut signaler que la fonction est terminée avant la lecture du fichier (problème n°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 mots clés async
et await
pour éviter ces deux problèmes. La plupart des API de l’écosystème Node.js ont été converties pour prendre en charge les promesses sous une forme donnée. Par exemple, à compter de la version 14, Node.js fournit une API fs/promises
pour remplacer l’API de rappel fs
.
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;
}
},
});
Avec async
et await
, vous n’avez pas besoin d’appeler le rappel context.done()
non plus.
// 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}`);
}
Résoudre les problèmes
Consultez le Guide de résolution des problèmes Node.js.
Étapes suivantes
Pour plus d’informations, consultez les ressources suivantes :