Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo riferimento spiega come sviluppare Funzioni di Azure usando JavaScript e TypeScript con il @azure/functions pacchetto npm. Per una panoramica generale dei concetti di Funzioni di Azure condivisi in tutti i linguaggi, consulta il riferimento per sviluppatori di Funzioni di Azure.
| Conto risorse | Link |
|---|---|
| Crea la tua prima funzione JavaScript | Visual Studio Code/CLI |
| Crea la tua prima funzione TypeScript | Visual Studio Code/CLI |
| Scenari e esempi | JavaScript/TypeScript |
| Informazioni di riferimento sulle API |
@azure/functions API |
Note
Questo articolo mostra il contenuto di una specifica versione del modello di programmazione basato sul selettore in cima alla pagina. La versione che scegli dovrebbe corrispondere alla versione del pacchetto @azure/functions NPM. Non puoi mescolare le funzioni v3 e v4 nella stessa app. Se non hai il pacchetto nel tuo package.json, il valore predefinito è v3.
Modello di programmazione
Funzioni di Azure per Node.js supporta due versioni di modello di programmazione. I nuovi progetti dovrebbero usare la v4.
| Feature | v4 (consigliato) | v3 |
|---|---|---|
| Condizione | GA | GA (manutenzione) |
@azure/functions pacchetto |
4.x | 3.x |
| Registrazione delle funzioni | Incentrato sul codice (app.http(), app.timer()) |
Basato su file (function.json) |
| Struttura dei file | Flessibile | Corretto (una cartella per funzione) |
| Versione di runtime di Funzioni | 4.25+ | 4.x |
| versioni di Node.js | 24.x, 22.x | 24.x, 22.x |
Nel modello di programmazione Node.js v4, si registrano funzioni importando l'oggetto app da @azure/functions e chiamando metodi specifici per trigger. Le funzioni sono definite direttamente nel tuo codice con una struttura file flessibile. Ogni funzione ha un singolo trigger che avvia la sua esecuzione e può anche avere binding, che sono connessioni dichiarative ad altri servizi per leggere i dati di input o scrivere dati di output. Per ulteriori informazioni, vedi trigger e associazioni.
Nel modello v4, tu:
- Registrare funzioni usando metodi specifici per trigger come
app.http(),app.timer(), eapp.storageQueue(). - Accedi al valore di input del trigger come primo parametro del tuo handler (ad esempio,
HttpRequest). - Restituisci l'output primario direttamente dalla funzione handler.
- Usa
context.extraInputs.get()per leggere da binding di input aggiuntivi come gestione rete virtuale di Azure. - Usa
context.extraOutputs.set()per scrivere in binding di output aggiuntivi come le code. - Ogni funzione ha esattamente un trigger, ma può avere più input e output aggiuntivi.
- Puoi memorizzare in cache i dati nelle variabili globali per il riutilizzo tra le invocazioni, ma non affidarti a questo stato per persistere. Il tempo di esecuzione può riciclare il tuo lavoratore in qualsiasi momento.
Nel modello di programmazione Node.js v3, si definisce ogni funzione utilizzando un function.json file di configurazione e il corrispondente codice JavaScript o TypeScript. Organizzi le funzioni in cartelle separate con strutture file specifiche. Ogni funzione ha un singolo trigger che avvia la sua esecuzione e può anche avere binding, che sono connessioni dichiarative ad altri servizi per leggere i dati di input o scrivere dati di output. Per altre informazioni, vedere trigger e associazioni.
Nel modello v3, tu:
- Definisci trigger e binding in un
function.jsonfile. Usadirection: "in"sia per ingressi chedirection: "out"per uscite. - Accedi all'input del trigger come secondo argomento al tuo handler, oppure leggilo da
context.bindings. - Imposta le uscite assegnando valori a
context.bindings(ad esempio,context.bindings.outputQueue). Per HTTP, usacontext.res. - I progetti TypeScript richiedono una
scriptFileproprietà infunction.jsonche punti al file JavaScript compilato. - Ogni funzione ha esattamente un trigger, ma può avere più associazioni di input e output.
- Puoi memorizzare in cache i dati nelle variabili globali per il riutilizzo tra le invocazioni, ma non affidarti a questo stato per persistere. Il tempo di esecuzione può riciclare il tuo lavoratore in qualsiasi momento.
Examples
Ecco una funzione semplice che risponde a una richiesta 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}!` };
}
});
Il seguente esempio non-HTTP utilizza un trigger timer:
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());
}
});
Il seguente esempio mostra un trigger HTTP con un binding di uscita in coda:
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 } };
}
});
Ecco una funzione semplice che risponde a una richiesta 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}!`
};
};
Il seguente esempio non-HTTP utilizza un trigger timer:
{
"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());
};
Il seguente esempio mostra un trigger HTTP con un binding di uscita in coda:
{
"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 }
};
};
Creazione dell'app di funzione
Questa sezione copre i componenti essenziali per creare e strutturare la tua app funzione Node, inclusa la @azure/functions libreria, la struttura del progetto e la gestione dei pacchetti.
Libreria @azure/functions
La @azure/functions libreria TypeScript/JavaScript fornisce i tipi e le funzioni principali che utilizzi per interagire con l'runtime di Funzioni di Azure. Per visualizzare tutti i tipi e i metodi disponibili, visitare l'API@azure/functions.
Il codice della funzione può usare @azure/functions per:
- Registrare funzioni e definire i trigger (modello v4).
- Accedi ai dati di input dei trigger con tipizzazione forte (ad esempio,
HttpRequest,Timer). - Creare valori di output tipati (come
HttpResponseInit). - Interagire con il contesto fornito dal runtime e i dati di binding.
Se utilizzi @azure/functions nella tua app, includilo tra le dipendenze del progetto:
{
"dependencies": {
"@azure/functions": "^4.0.0"
}
}
Note
La @azure/functions libreria definisce la superficie di programmazione per Node.js Funzioni di Azure, ma non è un SDK generico. Usarlo in modo specifico per la creazione e l'esecuzione di funzioni all'interno del runtime Funzioni di Azure.
Configurazione di TypeScript
Per ottenere la migliore esperienza di sviluppo con TypeScript, assicurati che il tuo tsconfig.json includa la configurazione corretta:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "dist",
"rootDir": ".",
"sourceMap": true,
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Struttura di cartelle
Un progetto JavaScript richiede la struttura di cartelle mostrata nel seguente esempio:
<project_root>/
| - .vscode/
| - node_modules/
| - myFirstFunction/
| | - index.js
| | - function.json
| - mySecondFunction/
| | - index.js
| | - function.json
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
La cartella principale del progetto, <project_root>, può contenere i file seguenti:
- .vscode/: (facoltativo) Contiene la configurazione Visual Studio Code archiviata. Per altre informazioni, vedere impostazioni Visual Studio Code.
- myFirstFunction/function.json: contiene la configurazione per il trigger, gli input e gli output della funzione. Il nome della directory determina il nome della funzione.
- myFirstFunction/index.js: archivia il codice della funzione. Per modificare questo percorso di file predefinito, vedere Uso di scriptFile.
- .funcignore: (Facoltativo) Dichiara i file che non devono essere pubblicati in Azure. Di solito, questo file contiene .vscode/ per ignorare le impostazioni dell'editor, test/ ignorare casi di test e local.settings.json per impedire la pubblicazione delle impostazioni locali dell'app.
- host.json: contiene opzioni di configurazione che influiscono su tutte le funzioni in un'istanza dell'app per le funzioni. Questo file viene pubblicato su Azure. Non tutte le opzioni sono supportate durante l'esecuzione in locale. Per altre informazioni, vedere host.json.
- local.settings.json: viene usato per archiviare le impostazioni dell'app e le stringhe di connessione durante l'esecuzione in locale. Questo file non viene pubblicato in Azure. Per altre informazioni, vedere local.settings.file.
- package.json: Contiene opzioni di configurazione come una lista delle dipendenze dei pacchetti, il punto di ingresso principale e script.
Un progetto JavaScript segue la struttura di cartelle consigliata nel seguente esempio:
<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
La cartella principale del progetto, <project_root>, può contenere i file seguenti:
- .vscode/: (facoltativo) Contiene la configurazione Visual Studio Code archiviata. Per altre informazioni, vedere impostazioni Visual Studio Code.
- src/functions/: percorso predefinito per tutte le funzioni e i relativi trigger e associazioni correlati.
- test/: (facoltativo) Contiene i test case dell'app per le funzioni.
- .funcignore: (Facoltativo) Dichiara i file che non devono essere pubblicati in Azure. Di solito, questo file contiene .vscode/ per ignorare le impostazioni dell'editor, test/ ignorare casi di test e local.settings.json per impedire la pubblicazione delle impostazioni locali dell'app.
- host.json: contiene opzioni di configurazione che influiscono su tutte le funzioni in un'istanza dell'app per le funzioni. Questo file viene pubblicato su Azure. Non tutte le opzioni sono supportate durante l'esecuzione in locale. Per altre informazioni, vedere host.json.
- local.settings.json: viene usato per archiviare le impostazioni dell'app e le stringhe di connessione durante l'esecuzione in locale. Questo file non viene pubblicato in Azure. Per altre informazioni, vedere local.settings.file.
- package.json: Contiene opzioni di configurazione come una lista delle dipendenze dei pacchetti, il punto di ingresso principale e script.
Gestione dei pacchetti
Una gestione efficace dei pacchetti è fondamentale per Node.js Funzioni di Azure progetti. Questa sezione tratta la gestione delle dipendenze, la configurazione dei pacchetti e le migliori pratiche per mantenere le dipendenze delle tue function app.
Gestione delle dipendenze
Tutti i Node.js Funzioni di Azure progetti usano npm per la gestione dei pacchetti. Il tuo package.json file definisce la configurazione del progetto, le dipendenze e gli script necessari per costruire ed eseguire le tue funzioni.
Struttura essenziale di 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. dipendenze di sviluppo
Separati adeguatamente le tue dipendenze:
Dipendenze di runtime (dependencies):
-
@azure/functions: La libreria principale di Funzioni di Azure - Librerie di business logic (lodash, axios e pacchetti simili)
- Driver di database (mongodb, mssql e pacchetti simili)
- Azure SDK pacchetti (@azure/storage-blob, @azure/cosmos, e pacchetti simili)
Dipendenze di sviluppo (devDependencies):
- Compilatore TypeScript e definizioni di tipo
- Framework di test (Jest, Mocha)
- Strumenti di build e linter
- Funzioni di Azure Core Tools (per lo sviluppo locale)
Pacchetti specifici per TypeScript
Per i progetti TypeScript, includere queste dipendenze essenziali di sviluppo:
{
"devDependencies": {
"@types/node": "^18.0.0",
"typescript": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0"
}
}
Sicurezza e aggiornamenti
Aggiorna regolarmente le tue dipendenze per affrontare vulnerabilità di sicurezza:
# Check for outdated packages
npm outdated
# Update packages
npm update
# Audit for security issues
npm audit
npm audit fix
Esecuzione e debug
Questa sezione copre lo sviluppo locale, le tecniche di debug e le strategie di test per Node.js Funzioni di Azure.
Configurazione di sviluppo locale
Prerequisiti:
- Node.js versione 18.x o 20.x
- Funzioni di Azure Core Tools v4.x
- Interfaccia della riga di comando di Azure (facoltativo)
Procedura di configurazione:
Installare le dipendenze:
npm installCompila i progetti TypeScript:
npm run buildAvvia l'esecuzione locale:
npm start # or directly: func start
Configurazione dell'ambiente
Configura il tuo ambiente di sviluppo locale utilizzando 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
}
}
Debugging
Debug di Visual Studio Code:
Creare .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Node Functions",
"type": "node",
"request": "attach",
"port": 9229,
"preLaunchTask": "func: host start"
}
]
}
Creare .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}"
}
}
]
}
Debug in linea di comando:
# Start with debugging enabled
func start --p <port>
# For TypeScript, ensure you build first
npm run build
func start --p 9229
Distribuzione
Questa sezione copre le strategie di deployment, l'integrazione CI/CD e le migliori pratiche di produzione per Node.js Funzioni di Azure.
Metodi di distribuzione
1. Distribuzione di Visual Studio Code:
- Installa l'estensione Funzioni di Azure.
- Fai clic con il pulsante destro sull'app per le funzioni nel pannello Azure.
- Selezionare Distribuisci in Function App.
2. Funzioni di Azure Core Tools:
# Deploy to Azure
func azure functionapp publish <FunctionAppName>
# Deploy with custom settings
func azure functionapp publish <FunctionAppName> --build local --publish-local-settings
3. interfaccia della riga di comando di Azure deployment:
# Deploy from local folder
az functionapp deployment source config-zip \
--resource-group <ResourceGroupName> \
--name <FunctionAppName> \
--src <PathToZipFile>
Configurazione di produzione
Impostazioni applicative in Azure:
Configura le variabili ambientali per la produzione:
-
WEBSITE_NODE_DEFAULT_VERSION: impostato su~18o~20. -
FUNCTIONS_WORKER_RUNTIME: impostare sunode. - Stringhe di connessione e chiavi API come impostazioni sicure dell'app.
-
NODE_ENV: impostare suproduction.
Trigger e associazioni
Funzioni di Azure usa trigger per avviare l'esecuzione della funzione e bindings per connettere il codice ad altri servizi come archiviazione, coda e database. Nel modello di programmazione Node.js, dichiari i binding in modo diverso a seconda della versione del modello.
Esistono due tipi principali di associazioni:
- Trigger (input che avvia la funzione)
- Input e output (origini dati o destinazioni aggiuntive)
Per altre informazioni sui trigger e le associazioni disponibili, vedere Triggers and Bindings in Funzioni di Azure.
Esempio: Timer Trigger con input Blob
Questa funzione si attiva ogni 10 minuti, legge da un Blob usando input aggiuntivi e registra il contenuto del 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}`);
}
});
Questa funzione si attiva ogni 10 minuti, legge da un Blob usando la configurazione dei bindings e registra il contenuto del 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}`);
};
Esempio: Trigger HTTP con uscita in coda
Questa funzione si attiva su una richiesta HTTP, scrive un messaggio in una coda di archiviazione e restituisce una risposta 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.`
};
}
});
Questa funzione si attiva su una richiesta HTTP, scrive un messaggio in una coda di archiviazione e restituisce una risposta 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.`
};
};
Gli oggetti app, trigger, input e output esportati dal modulo @azure/functions forniscono metodi specifici del tipo per la maggior parte dei tipi. Per tutti i tipi non supportati, viene fornito un metodo generic per consentire di specificare manualmente la configurazione. Il metodo generic può essere usato anche se si desidera modificare le impostazioni predefinite fornite da un metodo specifico del tipo.
L'esempio seguente è una semplice funzione attivata tramite HTTP usando metodi generici anziché metodi specifici del tipo.
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!` };
},
});
::: zona di fondo
Contesto di chiamata
Ogni invocazione della tua funzione riceve un oggetto di invocazione context. Usa questo oggetto per leggere input, impostare output, scrivere nei log e accedere a vari metadati. Nel modello v3, passi sempre l'oggetto di contesto come primo argomento al tuo gestore.
L'oggetto context include le seguenti proprietà:
| Proprietà | Descrizione |
|---|---|
invocationId |
L'ID della chiamata di funzione corrente. |
executionContext |
Vedere il contesto di esecuzione. |
bindings |
Vedere le associazioni. |
bindingData |
Metadati relativi all'input del trigger per questa invocazione, escludendo il valore stesso. Ad esempio, un trigger dell'hub eventi ha una proprietà enqueuedTimeUtc. |
traceContext |
Contesto per la traccia distribuita. Per altre informazioni, vedere Trace Context. |
bindingDefinitions |
La configurazione degli input e degli output, come definito in function.json. |
req |
Vedere richiesta HTTP. |
res |
Vedere risposta HTTP. |
context.executionContext
L'oggetto context.executionContext ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
invocationId |
L'ID della chiamata di funzione corrente. |
functionName |
Il nome della funzione che stai invocando. Il nome della cartella contenente il file function.json determina il nome della funzione. |
functionDirectory |
Cartella contenente il file function.json. |
retryContext |
Vedere il contesto di ripetizione dei tentativi. |
context.executionContext.retryContext
L'oggetto context.executionContext.retryContext ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
retryCount |
Numero che rappresenta il tentativo di ripetizione corrente. |
maxRetryCount |
Numero massimo di tentativi di esecuzione. Un valore di -1 indica di riprovare per un periodo illimitato. |
exception |
Eccezione che ha causato il nuovo tentativo. |
context.bindings
Usa l'oggetto context.bindings per leggere input o impostare output. L'esempio seguente è un trigger della coda di archiviazione che usa context.bindings per copiare un blob di archiviazione di input in un blob di archiviazione di output. Il contenuto del messaggio della coda sostituisce {queueTrigger} come nome file da copiare, con l'aiuto di un'espressione di associazione.
{
"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
Il metodo context.done è deprecato. Prima che Funzioni di Azure supportasse funzioni asincrone, segnalavi che la tua funzione era stata eseguita chiamando context.done():
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
Rimuovere la chiamata a context.done(). Segna la tua funzione come asincrona così che restituisca una promessa (anche se non await hai nulla). Al termine della funzione (in altre parole, la promessa restituita viene risolta), il modello v3 sa che viene eseguita la funzione.
module.exports = async function (context, request) {
context.log("you don't need context.done or an awaited call");
};
Ogni invocazione della tua funzione riceve un context oggetto di invocazione. Questo oggetto contiene informazioni sulla tua invocazione e sui metodi di registrazione. Nel modello v4, di solito si passa l'oggetto context come secondo argomento al tuo handler.
La InvocationContext classe include le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
invocationId |
L'ID della chiamata di funzione corrente. |
functionName |
Nome della funzione. |
extraInputs |
Usato per ottenere i valori di input aggiuntivi. Per altre informazioni, vedere input e output aggiuntivi. |
extraOutputs |
Utilizzato per impostare i valori di output aggiuntivi. Per altre informazioni, vedere input e output aggiuntivi. |
retryContext |
Vedere il contesto di ripetizione dei tentativi. |
traceContext |
Contesto per la traccia distribuita. Per altre informazioni, vedere Trace Context. |
triggerMetadata |
Metadati relativi all'input del trigger per questa chiamata, non incluso il valore stesso. Ad esempio, un trigger dell'hub eventi ha una proprietà enqueuedTimeUtc. |
options |
Le opzioni utilizzate durante la registrazione della funzione, dopo che sono state validate e i valori predefiniti, sono esplicitamente specificate. |
Contesto di ripetizione dei tentativi
L'oggetto retryContext ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
retryCount |
Numero che rappresenta il tentativo di ripetizione corrente. |
maxRetryCount |
Numero massimo di tentativi di esecuzione. Un valore di -1 indica di riprovare per un periodo illimitato. |
exception |
Eccezione che ha causato il nuovo tentativo. |
Per altre informazioni, vedere retry-policies.
Registrazione
In Funzioni di Azure, usa context.log() per scrivere i log. Funzioni di Azure si integra con applicazione Azure Insights per acquisire meglio i log dell'app per le funzioni. Application Insights, parte di Monitoraggio di Azure, offre funzionalità per la raccolta, il rendering visivo e l'analisi dei log applicazioni e degli output di traccia. Per altre informazioni, vedere monitoraggio Funzioni di Azure.
Note
Se usi il metodo alternativo Node.js console.log , i log a livello di app vengono tracciati ma non associati a una funzione specifica. Usa context per la registrazione invece che console per far sì che tutti i log siano associati a una funzione specifica.
Nell'esempio seguente viene scritto un log a livello di "informazioni" predefinito, incluso l'ID chiamata:
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
Livelli di registrazione
Oltre al metodo predefinito context.log , si usano i seguenti metodi per scrivere log a livelli specifici:
| Metodo | Descrizione |
|---|---|
context.log.error() |
Scrive un evento a livello di errore nei log. |
context.log.warn() |
Scrive un evento a livello di avviso nei log. |
context.log.info() |
Scrive un evento a livello di informazioni nei log. |
context.log.verbose() |
Scrive un evento a livello di traccia nei log. |
| Metodo | Descrizione |
|---|---|
context.trace() |
Scrive un evento a livello di traccia nei log. |
context.debug() |
Scrive un evento a livello di debug nei log. |
context.info() |
Scrive un evento a livello di informazioni nei log. |
context.warn() |
Scrive un evento a livello di avviso nei log. |
context.error() |
Scrive un evento a livello di errore nei log. |
Configurare il livello di log
Functions ti permette di definire il livello di soglia per tracciare e visualizzare i log. Per impostare la soglia, utilizzare la proprietà logging.logLevel nel file host.json. Questa proprietà ti permette di definire un livello predefinito per tutte le funzioni o una soglia per ogni singola funzione. Per altre informazioni, vedere Come configurare il monitoraggio per Funzioni di Azure.
Tenere traccia dei dati personalizzati
Per impostazione predefinita, Funzioni di Azure scrive l'output come tracce in Application Insights. Per maggiore controllo, usa l'SDK di Application Insights Node.js per inviare log, metriche e dipendenze personalizzate alla tua istanza di Application Insight.
Note
I metodi in Application Insights Node.js SDK possono cambiare nel tempo. Potrebbero esserci piccole differenze di sintassi rispetto agli esempi illustrati di seguito. Per gli esempi di utilizzo più recenti dell'API, vedere la documentazione di Application Insights Node.js SDK.
Per il tracciamento distribuito nel modello di programmazione Node.js v4, usa il @azure/functions-opentelemetry-instrumentation pacchetto invece dell'SDK Application Insights. Questo pacchetto fornisce la strumentazione automatica basata su OpenTelemetry per Funzioni di Azure. Per altre informazioni, vedere il repository OpenTelemetry Funzioni di Azure Instrumentation for 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,
});
};
Il parametro tagOverrides imposta operation_Id sull'ID di chiamata alla funzione. Questa impostazione ti permette di correlare tutti i log generati automaticamente e personalizzati per una determinata invocazione di funzione.
Trigger HTTP
I trigger HTTP e webhook usano oggetti richiesta e risposta per rappresentare i messaggi HTTP.
I trigger HTTP e webhook usano oggetti HttpRequest e HttpResponse per rappresentare i messaggi HTTP. Le classi rappresentano un subset del recupero standard, usando il pacchetto undici di Node.js.
Richiesta HTTP
Accedi alla richiesta in diversi modi:
Come secondo argomento della funzione:
module.exports = async function (context, request) { context.log(`Http function processed request for url "${request.url}"`);
Dalla proprietà
context.req:module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.req.url}"`);
Dai binding di input nominati: Questa opzione funziona come qualsiasi binding non HTTP. Il nome dell'associazione in
function.jsondeve corrispondere alla chiave incontext.bindingso "request1" nell'esempio seguente:{ "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'oggetto HttpRequest ha le proprietà seguenti:
| Proprietà | TIPO | Descrizione |
|---|---|---|
method |
string |
Metodo di richiesta HTTP usato per richiamare questa funzione. |
url |
string |
URL richiesta. |
headers |
Record<string, string> |
Intestazioni di richiesta HTTP. Questo oggetto fa distinzione tra maiuscole e minuscole. Usa invece request.getHeader('header-name'), che non fa distinzione tra maiuscole e minuscole. |
query |
Record<string, string> |
Chiavi e valori dei parametri della stringa di query dall'URL. |
params |
Record<string, string> |
Indirizzare chiavi e valori dei parametri. |
user |
HttpRequestUser \| null |
Oggetto che rappresenta l'utente connesso, tramite l'autenticazione di Funzioni, l'autenticazione SWA o null quando tale utente non è connesso. |
body |
Buffer \| string \| any |
Se il tipo di supporto è "application/octet-stream" o "multipart/*", body è un buffer. Se il valore è una stringa in grado di analizzare JSON, body è l'oggetto analizzato. In caso contrario, body è una stringa. |
rawBody |
string |
Corpo come stringa. Nonostante il nome, questa proprietà non restituisce un buffer. |
bufferBody |
Buffer |
Corpo come buffer. |
Puoi accedere alla richiesta come primo argomento per il tuo handler per una funzione attivata da HTTP.
async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
L'oggetto HttpRequest ha le proprietà seguenti:
| Proprietà | TIPO | Descrizione |
|---|---|---|
method |
string |
Metodo di richiesta HTTP usato per richiamare questa funzione. |
url |
string |
URL richiesta. |
headers |
Headers |
Intestazioni di richiesta HTTP. |
query |
URLSearchParams |
Chiavi e valori dei parametri della stringa di query dall'URL. |
params |
Record<string, string> |
Indirizzare chiavi e valori dei parametri. |
user |
HttpRequestUser \| null |
Oggetto che rappresenta l'utente connesso, tramite l'autenticazione di Funzioni, l'autenticazione SWA o null quando tale utente non è connesso. |
body |
ReadableStream \| null |
Corpo come flusso leggibile. |
bodyUsed |
boolean |
Valore booleano che indica se il corpo è già letto. |
Per accedere al corpo di una richiesta o risposta, utilizzare i seguenti metodi:
| Metodo | Tipo restituito |
|---|---|
arrayBuffer() |
Promise<ArrayBuffer> |
blob() |
Promise<Blob> |
formData() |
Promise<FormData> |
json() |
Promise<unknown> |
text() |
Promise<string> |
Note
Puoi eseguire le funzioni corporee solo una volta. Le chiamate successive si risolvono con stringhe vuote o ArrayBuffer.
Risposta HTTP
Puoi impostare la risposta in diversi modi. Ad esempio, è possibile usare:
Impostare la proprietà
context.res:module.exports = async function (context, request) { context.res = { body: `Hello, world!` };
Restituire la risposta: se la funzione è asincrona e si imposta il nome dell'associazione su
$returninfunction.json, è possibile restituire la risposta direttamente anziché impostarla sucontext.{ "type": "http", "direction": "out", "name": "$return" }module.exports = async function (context, request) { return { body: `Hello, world!` };
Imposta il binding di output denominato: Questa opzione funziona allo stesso modo di qualsiasi altro binding non HTTP. Il nome dell'associazione in
function.jsondeve corrispondere alla chiave incontext.bindingso "response1" nell'esempio seguente:{ "type": "http", "direction": "out", "name": "response1" }module.exports = async function (context, request) { context.bindings.response1 = { body: `Hello, world!` };
Chiamare
context.res.send(): questa opzione è deprecata. Chiamacontext.done()implicitamente e non puoi usarlo in una funzione asincrona.module.exports = function (context, request) { context.res.send(`Hello, world!`);
Se si crea un nuovo oggetto quando si imposta la risposta, tale oggetto deve corrispondere all'interfaccia HttpResponseSimple, che ha le proprietà seguenti:
| Proprietà | TIPO | Descrizione |
|---|---|---|
headers |
Record<string, string> (facoltativo) |
Intestazioni di risposta HTTP. |
cookies |
Cookie[] (facoltativo) |
Cookie di risposta HTTP. |
body |
any (facoltativo) |
Corpo della risposta HTTP. |
statusCode |
number (facoltativo) |
Codice di stato della risposta HTTP. Se non è impostato, il valore predefinito è 200. |
status |
number (facoltativo) |
Uguale a statusCode. Questa proprietà viene ignorata se statusCode è impostata. |
È anche possibile modificare l'oggetto context.res senza sovrascriverlo. L'oggetto context.res predefinito usa l'interfaccia HttpResponseFull, che supporta i metodi seguenti oltre alle proprietà HttpResponseSimple:
| Metodo | Descrizione |
|---|---|
status() |
Imposta lo stato. |
setHeader() |
Imposta un campo di intestazione.
NOTA:res.set() e res.header() sono anche supportati e fanno la stessa cosa. |
getHeader() |
Riceve un campo di testa.
NOTA:res.get() è anche supportata e fa la stessa cosa. |
removeHeader() |
Rimuove un'intestazione. |
type() |
Imposta l'intestazione "content-type". |
send() |
Questo metodo è deprecato. Imposta il corpo e chiama context.done() per indicare che una funzione di sincronizzazione è stata completata.
NOTA:res.end() è anche supportata e fa la stessa cosa. |
sendStatus() |
Questo metodo è deprecato. Imposta il codice di stato e chiama context.done() per indicare che una funzione di sincronizzazione è stata completata. |
json() |
Questo metodo è deprecato. Imposta "content-type" su "application/json", imposta il corpo e chiama context.done() per indicare che una funzione di sincronizzazione è terminata. |
Puoi impostare la risposta in diversi modi. Ad esempio, è possibile usare:
Un'interfaccia semplice con tipo
HttpResponseInit: Questa opzione è il modo più conciso per restituire le risposte.return { body: `Hello, world!` };
L'interfaccia HttpResponseInit ha le proprietà seguenti:
| Proprietà | TIPO | Descrizione |
|---|---|---|
body |
BodyInit (facoltativo) |
Corpo della risposta HTTP come uno dei ArrayBuffer, AsyncIterable<Uint8Array>, Blob, FormData, Iterable<Uint8Array>, NodeJS.ArrayBufferView, URLSearchParams, null o string. |
jsonBody |
any (facoltativo) |
Corpo della risposta HTTP serializzabile in JSON. Se impostata, la proprietà HttpResponseInit.body viene ignorata a favore di questa proprietà. |
status |
number (facoltativo) |
Codice di stato della risposta HTTP. Se non è impostato, il valore predefinito è 200. |
headers |
HeadersInit (facoltativo) |
Intestazioni di risposta HTTP. |
cookies |
Cookie[] (facoltativo) |
Cookie di risposta HTTP. |
Come classe con tipo
HttpResponse: questa opzione fornisce metodi helper per la lettura e la modifica di varie parti della risposta, ad esempio le intestazioni.const response = new HttpResponse({ body: `Hello, world!` }); response.headers.set("content-type", "application/json"); return response;
La classe HttpResponse accetta un HttpResponseInit facoltativo come argomento per il relativo costruttore e ha le proprietà seguenti:
| Proprietà | TIPO | Descrizione |
|---|---|---|
status |
number |
Codice di stato della risposta HTTP. |
headers |
Headers |
Intestazioni di risposta HTTP. |
cookies |
Cookie[] |
Cookie di risposta HTTP. |
body |
ReadableStream | null |
Corpo come flusso leggibile. |
bodyUsed |
boolean |
Valore booleano che indica se il corpo è già letto. |
Flussi HTTP
I flussi HTTP sono una funzionalità che semplifica l'elaborazione di dati di grandi dimensioni, lo streaming di risposte OpenAI, la distribuzione di contenuto dinamico e il supporto di altri scenari HTTP principali. Consente di trasmettere le richieste e le risposte dagli endpoint HTTP nell'app per le funzioni Node.js. Usare i flussi HTTP negli scenari in cui l'app richiede lo scambio in tempo reale e l'interazione tra client e server tramite HTTP. È anche possibile usare flussi HTTP per ottenere prestazioni e affidabilità ottimali per le app quando si usa HTTP.
Importante
I flussi HTTP non sono supportati nel modello v3.
Eseguire l'aggiornamento al modello v4 per usare la funzionalità di streaming HTTP.
I tipi HttpRequest e HttpResponse esistenti nel modello di programmazione v4 supportano già vari modi per gestire il corpo del messaggio, tra cui come flusso.
Prerequisiti
- Il pacchetto
@azure/functionsnpm versione 4.3.0 o successiva. - Funzioni di Azure runtime versione 4.28 o successiva.
- Funzioni di Azure Core Tools versione 4.0.5530 o successiva, che contiene la versione di esecuzione corretta.
Abilitare i flussi
Usare questi passaggi per abilitare i flussi HTTP nell'app per le funzioni in Azure e nei progetti locali:
Se si prevede di trasmettere grandi quantità di dati, modificare l'impostazione
FUNCTIONS_REQUEST_BODY_SIZE_LIMITin Azure. La dimensione massima consentita di default è104857600, che limita le tue richieste a circa 100 MB.Per lo sviluppo locale, aggiungere anche
FUNCTIONS_REQUEST_BODY_SIZE_LIMITal file local.settings.json.Aggiungere il codice seguente all'app in qualsiasi file incluso nel campo principale.
const { app } = require("@azure/functions"); app.setup({ enableHttpStream: true });
Esempi di flusso
L'esempio seguente mostra una funzione attivata da HTTP che riceve dati tramite una richiesta HTTP POST. La funzione trasmette questi dati in un file di output specificato:
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!' };
},
});
Il seguente esempio mostra una funzione attivata da HTTP che trasmette il contenuto di un file come risposta alle richieste HTTP GET in arrivo:
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 };
},
});
Per un'app di esempio pronta a usare che utilizza stream, dai un'occhiata a questo esempio su GitHub.
Considerazioni sul flusso
- Usalo
request.bodyper ottenere il massimo beneficio dall'uso degli stream. Puoi comunque usare metodi comerequest.text(), che restituiscono sempre il corpo come una stringa.
Hook
Il modello v3 non supporta i ganci. Eseguire l'aggiornamento al modello v4 per usare gli hook.
Usare un hook per eseguire codice in punti diversi del ciclo di vita Funzioni di Azure. L'ordine in cui registri i hook determina l'ordine in cui vengono eseguiti. Puoi registrare hook da qualsiasi file nella tua app. Esistono due livelli di hook: a livello di app e a livello di invocazione.
Hook di chiamata
Gli hook di invocazione si attivano una volta per ogni invocazione della tua funzione. Un preInvocation hook corre prima che la funzione venga eseguita, e un postInvocation hook dopo che la funzione venga eseguita. Di default, il tuo hook viene eseguito per tutti i tipi di trigger, ma puoi anche filtrare per tipo. L'esempio seguente illustra come registrare un hook di chiamata e filtrare in base al tipo di trigger:
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']
});
Il primo argomento del gestore hook è un oggetto di contesto specifico di tale tipo di hook.
L'oggetto PreInvocationContext ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
inputs |
Gli argomenti li trasmetti all'invocazione. |
functionHandler |
Gestore della funzione per la chiamata. Le modifiche apportate a questo valore influiscono sulla funzione stessa. |
invocationContext |
L’oggetto contesto di chiamata passato alla funzione. |
hookData |
Posizione consigliata per archiviare e condividere dati tra hook nello stesso ambito. Usa un nome di proprietà unico in modo che non entri in conflitto con i dati di altri hook. |
L'oggetto PostInvocationContext ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
inputs |
Gli argomenti li trasmetti all'invocazione. |
result |
Risultato della funzione. Le modifiche apportate a questo valore influiscono sul risultato complessivo della funzione. |
error |
Errore generato dalla funzione o null/undefined se non è presente alcun errore. Le modifiche apportate a questo valore influiscono sul risultato complessivo della funzione. |
invocationContext |
L’oggetto contesto di chiamata passato alla funzione. |
hookData |
Posizione consigliata per archiviare e condividere dati tra hook nello stesso ambito. Usa un nome di proprietà unico in modo che non entri in conflitto con i dati di altri hook. |
Hook dell'app
Il runtime esegue gli hook dell'app una sola volta per ciascuna istanza della tua app. Esegue gli hook appStart durante l'avvio e gli hook appTerminate durante l'arresto. Gli hook di terminazione dell'app hanno un tempo limitato per l'esecuzione e non vengono eseguiti in tutti gli scenari.
Il runtime di Funzioni di Azure attualmente non supporta la registrazione del contesto al di fuori di un'invocazione. Usare il pacchetto npm di Application Insights per registrare i dati durante gli hook a livello di app.
L'esempio seguente registra gli hook dell'app:
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 }));
});
Il primo argomento del gestore hook è un oggetto di contesto specifico di tale tipo di hook.
L'oggetto AppStartContext possiede la seguente proprietà:
| Proprietà | Descrizione |
|---|---|
hookData |
Posizione consigliata per archiviare e condividere dati tra hook nello stesso ambito. Usa un nome di proprietà unico in modo che non entri in conflitto con i dati di altri hook. |
L'oggetto AppTerminateContext possiede la seguente proprietà:
| Proprietà | Descrizione |
|---|---|
hookData |
Posizione consigliata per archiviare e condividere dati tra hook nello stesso ambito. Usa un nome di proprietà unico in modo che non entri in conflitto con i dati di altri hook. |
Migliori pratiche per gli hook
Quando utilizzi gli hook nelle tue Funzioni di Azure, considera queste best practice:
Considerazioni sulle prestazioni
- Mantenere il tempo di esecuzione del hook al minimo per evitare di compromettere le prestazioni della funzione.
- Utilizzare operazioni asincrone dove possibile per prevenire blocchi.
- Considera il sovraccarico degli hook quando elabori richieste ad alto volume.
Gestione degli errori
- Includi sempre una corretta gestione degli errori nei tuoi hook.
- Non lasciare che i guasti al gancio causino guasti funzionali a meno che non sia assolutamente necessario.
- Registra gli errori degli hook in modo appropriato per il debug.
Condivisione dei dati
- Usalo
hookDataper condividere informazioni tra gli hook pre e post invocazione. - Usa nomi di proprietà unici per evitare conflitti con altri agganci.
- Pulire i dati dei hook quando non sono più necessari per prevenire perdite di memoria.
Filtro
- Usa il filtraggio del tipo trigger per assicurarti che i hook vengano eseguiti solo per le funzioni rilevanti.
- Sii specifico con i tuoi filtri per ottimizzare le prestazioni.
Scalabilità e concorrenza
Per impostazione predefinita, Funzioni di Azure monitora automaticamente il carico nell'applicazione e crea più istanze host per Node.js in base alle esigenze. Funzioni di Azure utilizza soglie integrate (non configurabili dall'utente) per diversi tipi di trigger per decidere quando aggiungere istanze, come l'età dei messaggi e la dimensione della coda per QueueTrigger. Per altre informazioni, vedere Come funzionano i piani a consumo e Premium.
Questo comportamento di ridimensionamento è sufficiente per molte applicazioni Node.js. Per le applicazioni associate alla CPU, è possibile migliorare ulteriormente le prestazioni usando più processi di lavoro in linguaggio. È possibile aumentare il numero di processi di lavoro per host dal valore predefinito 1 a un massimo di 10 usando l'impostazione dell'applicazione FUNCTIONS_WORKER_PROCESS_COUNT. Funzioni di Azure prova quindi a distribuire uniformemente le chiamate di funzioni simultanee tra questi processi di lavoro. Questo comportamento rende meno probabile che una funzione a elevato utilizzo di CPU impedisca l'esecuzione di altre funzioni. L'impostazione si applica a ogni host che Funzioni di Azure crea quando si aumenta la scalabilità orizzontale dell'applicazione per soddisfare la domanda.
Avviso
Usare l'impostazione FUNCTIONS_WORKER_PROCESS_COUNT con cautela. Più processi in esecuzione nella stessa istanza possono causare un comportamento imprevedibile e aumentare i tempi di caricamento delle funzioni. Se usi questa impostazione, eseguire da un file package può compensare questi svantaggi.
Versione del nodo
È possibile visualizzare la versione corrente usata dal runtime registrando process.version da qualsiasi funzione. Per un elenco delle versioni di Node.js supportate da ogni modello di programmazione, vedere supported versions.
Impostazione della versione del nodo
Il modo in cui si aggiorna la versione Node.js dipende dal sistema operativo in cui viene eseguita l'app per le funzioni.
Quando viene eseguito su Windows, imposta la versione di Node.js usando l'impostazione dell'applicazione WEBSITE_NODE_DEFAULT_VERSION. Aggiorna questa impostazione utilizzando la interfaccia della riga di comando di Azure o tramite il portale Azure.
Per altre informazioni sulle versioni di Node.js, vedere Versioni supportate.
Prima di aggiornare la versione Node.js, assicurarsi che l'app per le funzioni sia in esecuzione nella versione più recente del runtime di Funzioni di Azure. Se è necessario aggiornare la versione del runtime, consultare Migrazione delle app da Funzioni di Azure versione 3.x alla versione 4.x.
Eseguire il comando interfaccia della riga di comando di Azure az functionapp config appsettings set per aggiornare la versione Node.js per l'app per le funzioni in esecuzione in Windows:
az functionapp config appsettings set --settings WEBSITE_NODE_DEFAULT_VERSION=~22 \
--name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>
Questo comando imposta l'impostazione dell'applicazioneWEBSITE_NODE_DEFAULT_VERSION alla versione ~22LTS supportata.
Dopo aver fatto modifiche, la tua app di funzione si riavvia. Per altre informazioni sul supporto delle funzioni per Node.js, vedere Language Runtime support policy.
Variabili di ambiente
Usa variabili di ambiente per gestire segreti operativi, come stringhe di connessione, chiavi ed endpoint. Usali anche per configurazioni di ambiente, come le variabili di profilo. Aggiungi variabili di ambiente sia nel tuo ambiente locale che cloud, e accedi a esse tramite process.env il codice della tua funzione.
L'esempio seguente registra la variabile di ambiente 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"]}`);
}
Nell’ambiente di sviluppo locale
Quando si esegue in locale, il progetto di funzioni include un file local.settings.json, in cui le variabili di ambiente vengono archiviate nell'oggetto Values.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"CUSTOM_ENV_VAR_1": "hello",
"CUSTOM_ENV_VAR_2": "world"
}
}
Nell'ambiente cloud Azure
Quando si esegue in Azure, l'app per le funzioni consente di impostare e usare Impostazioni di applicazione, ad esempio le stringhe di connessione del servizio, ed espone queste impostazioni come variabili di ambiente durante l'esecuzione.
Esistono diversi modi per aggiungere, aggiornare ed eliminare le impostazioni dell'app per le funzioni:
- In il portale di Azure
- Utilizzando l'interfaccia della riga di comando di Azure
- Utilizzando Azure PowerShell
Le modifiche apportate alle impostazioni dell'app per le funzioni richiedono il riavvio dell'app per le funzioni.
Variabili di ambiente del ruolo di lavoro
Node.js ha diverse variabili di ambiente Funzioni specifiche per essa:
languageWorkers__node__arguments
Usa questa impostazione per specificare argomentazioni personalizzate quando inizi il tuo processo Node.js. Più spesso, lo usi localmente per avviare il worker in modalità debug, ma puoi anche usarlo in Azure se hai bisogno di argomentazioni personalizzate.
Avviso
Se possibile, evita di usare languageWorkers__node__arguments in Azure perché può influire negativamente sui tempi di avvio a freddo. Anziché usare worker pre-riscaldati, il runtime deve avviare un nuovo worker da zero utilizzando gli argomenti personalizzati specificati.
registrazionelogLevelWorker
Usa questa impostazione per modificare il livello di log predefinito dei log dei worker specifici di Node.js. Per impostazione predefinita, vengono visualizzati solo i log degli avvisi o degli errori, ma è possibile impostarlo su information o debug per diagnosticare i problemi relativi al ruolo di lavoro Node.js. Per altre informazioni, vedere configurazione dei livelli di log.
Moduli ECMAScript (anteprima)
Note
I moduli ECMAScript sono attualmente una funzione di anteprima in Node.js 14 o superiori in Funzioni di Azure.
Moduli ECMAScript (moduli ES) sono il nuovo sistema di moduli standard ufficiale per Node.js. Finora, gli esempi di codice in questo articolo usano la sintassi CommonJS. Quando si esegue Funzioni di Azure in Node.js 14 o superiori, puoi scegliere di scrivere le tue funzioni usando la sintassi dei moduli ES.
Per usare i moduli ES in una funzione, modificare il nome file in modo da usare un'estensione .mjs. L'esempio di file index.mjs seguente è una funzione attivata da HTTP che usa la sintassi dei moduli ES per importare la libreria uuid e restituire un valore.
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,
});
Configurare il punto di ingresso della funzione
Usa le function.json proprietà scriptFile e entryPoint imposta la posizione e il nome della funzione esportata. Quando utilizzi TypeScript, è necessaria la proprietà scriptFile e dovrebbe puntare al file JavaScript compilato.
Utilizzo di scriptFile
Di default, una funzione JavaScript viene eseguita da index.js. Questo file si trova nella stessa directory padre del corrispondente file function.json.
Usalo scriptFile per organizzare la struttura delle cartelle. Il seguente esempio mostra un modo per configurare le cartelle:
<project_root>/
| - node_modules/
| - myFirstFunction/
| | - function.json
| - lib/
| | - sayHello.js
| - host.json
| - package.json
Il function.json file for myFirstFunction dovrebbe includere una scriptFile proprietà che punti al file con la funzione esportata da eseguire.
{
"scriptFile": "../lib/sayHello.js",
"bindings": [
...
]
}
Utilizzo di entryPoint
Nel modello v3, devi esportare una funzione usando module.exports così che la funzione possa essere trovata ed eseguita. Di default, la funzione che viene eseguita quando viene attivata è l'unica esportazione da quel file. Può anche essere l'esportazione denominata run o l'esportazione denominata index. L'esempio seguente imposta entryPoint in function.json su un valore personalizzato, "logHello":
{
"entryPoint": "logHello",
"bindings": [
...
]
}
async function logHello(context) {
context.log("Hello, world!");
}
module.exports = { logHello };
Consigli
Questa sezione descrive diversi modelli di impatto per Node.js app che dovresti seguire.
Scegliere i piani di servizio app con una singola vCPU
Quando crei un'app di funzioni che utilizza il piano App Service, seleziona un piano a singolo vCPU invece di un piano con più vCPU. Oggi, Functions esegue Node.js funzioni in modo più efficiente su VM a singolo vCPU, e l'uso di VM più grandi non porta i miglioramenti di prestazioni attesi. Quando necessario, puoi scalare aggiungendo più istanze VM a singolo vCPU, oppure puoi abilitare l'autoscala. Per altre informazioni, vedere Scalare il conteggio delle istanze manualmente o automaticamente.
Eseguire da un file di pacchetto
Quando si sviluppano Funzioni di Azure nel modello di hosting serverless, l'avvio a freddo è una realtà. Avvio a freddo fa riferimento alla prima volta che l'app per le funzioni inizia dopo un periodo di inattività, richiedendo più tempo per l'avvio. Per app Node.js con alberi delle dipendenze di grandi dimensioni, in particolare, l'avvio a freddo può essere significativo. Per velocizzare il processo di avvio a freddo eseguire le funzioni come un file di pacchetto quando possibile. Molte modalità di distribuzione usano questo modello per impostazione predefinita, ma se riscontri tempi elevati di avvio a freddo, verifica di usare questa modalità.
Usare async ed await
Quando scrivi funzioni di Azure in Node.js, scrivi il codice usando le parole chiave async e await. Scrivere codice usando async e await invece di callback o .then e .catch con Promises ti aiuta a evitare due problemi comuni:
- Generazione di eccezioni non rilevate che arrestano in modo anomalo il processo di Node.js, che potenzialmente influisce sull'esecuzione di altre funzioni.
- Comportamento imprevisto, ad esempio log mancanti da
context.log, causato da chiamate asincrone non attese correttamente.
Nell'esempio seguente il metodo asincrono fs.readFile viene richiamato con una funzione di callback error-first come secondo parametro. Questo codice causa entrambi i problemi menzionati in precedenza. Un'eccezione non rilevata in modo esplicito nell'ambito corretto può arrestare l'intero processo (problema 1). Restituire senza assicurarsi che il callback si concluda significa che la risposta HTTP a volte ha un corpo vuoto (problema #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 };
},
});
Nell'esempio seguente il metodo asincrono fs.readFile viene richiamato con una funzione di callback error-first come secondo parametro. Questo codice causa entrambi i problemi menzionati in precedenza. Un'eccezione che non è esplicitamente rilevata nell'ambito corretto può far crashare l'intero processo (problema #1). Chiamare il metodo obsoleto context.done() al di fuori dell'ambito del callback può segnalare che la funzione è terminata prima che il file venga letto (problema #2). In questo esempio, chiamare context.done() troppo presto genera voci di log mancanti a partire da 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();
};
Usa le async parole chiave e await per evitare entrambi questi problemi. La maggior parte delle API nell'ecosistema Node.js ora supporta promesse in qualche forma. Ad esempio, a partire dalla versione 14, Node.js fornisce un'API fs/promises per sostituire l'API fs di callback.
Nell'esempio seguente, tutte le eccezioni non gestite generate durante l'esecuzione della funzione non superano solo la singola chiamata che ha generato l'eccezione. La parola chiave await indica che i passaggi seguenti readFile vengono eseguiti solo dopo il completamento.
// 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;
}
},
});
Quando usi async e await, non è necessario chiamare il context.done() callback.
// 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}`);
};
Risolvere problemi
Vedere la guida alla risoluzione dei problemi Node.js.
Passaggi successivi
Per altre informazioni, vedere le seguenti risorse:
- Migliori pratiche per Funzioni di Azure
- Informazioni di riferimento per sviluppatori Funzioni di Azure
- Trigger e binding di Funzioni di Azure