Azure Functions Node.js ontwikkelaarsreferentie

Deze referentie behandelt hoe je Azure Functions kunt ontwikkelen met JavaScript en TypeScript met het @azure/functions npm-pakket. Voor een algemeen overzicht van Azure Functions-concepten die over alle talen worden gedeeld, zie de Azure Functions ontwikkelaarsreferentie.

Hulpbron Link
Maak je eerste JavaScript-functie Visual StudioCodeCLI/
Maak je eerste TypeScript-functie aan Visual StudioCodeCLI/
Scenario’s en voorbeelden JavaScript/TypeScript
API-referentie @azure/functions API

Notitie

Dit artikel toont inhoud voor een specifieke programmeermodelversie op basis van de selector bovenaan de pagina. De versie die je kiest moet overeenkomen met je @azure/functions npm-pakketversie. Je kunt v3- en v4-functies niet in dezelfde app mengen. Als je het pakket niet in je package.jsonhebt, is de standaard v3.

Programmeermodel

Azure Functions voor Node.js ondersteunt twee versies van programmeermodellen. Nieuwe projecten zouden v4 moeten gebruiken.

Feature v4 (aanbevolen) v3
Status Algemene Vergadering GA (onderhoud)
@azure/functions Pakket 4.x 3.x
Registratie van functies Op code gericht (app.http(), app.timer()) Bestandsgebaseerd (function.json)
Bestandsstructuur Buigzaam Vaste indeling (één map per functie)
Versie van de Functions-runtime 4.25+ 4.x
Node.js versies 24.x, 22.x 24.x, 22.x

In het Node.js v4 programmeermodel registreer je functies door het app object te importeren en @azure/functions trigger-specifieke methoden aan te roepen. De functies worden direct in je code gedefinieerd met een flexibele bestandsstructuur. Elke functie heeft één enkele trigger die de uitvoering start en kan ook bindings hebben, wat declaratieve verbindingen zijn met andere services voor het lezen van invoerdata of het schrijven van uitvoergegevens. Voor meer informatie, zie Triggers en bindingen.

In het v4-model moet je:

  • Registreer functies door gebruik te maken van trigger-specifieke methoden zoals app.http(), app.timer(), en app.storageQueue().
  • Toegang tot de trigger-invoer als eerste argument naar je handler (bijvoorbeeld, HttpRequest).
  • Geef de primaire output direct terug vanuit de handlerfunctie.
  • Gebruik context.extraInputs.get() om te lezen uit extra invoerbindingen, zoals Blob Storage.
  • Gebruik context.extraOutputs.set() om naar extra uitvoerbindingen zoals wachtrijen te schrijven.
  • Elke functie heeft precies één trigger, maar kan meerdere extra in- en uitgangen hebben.
  • Je kunt gegevens cachen in globale variabelen voor hergebruik tussen aanroepen, maar ga er niet van uit dat deze toestand behouden blijft. De runtime kan je werknemer op elk moment recyclen.

In het Node.js v3 programmeermodel definieer je elke functie door gebruik te maken van een function.json configuratiebestand en bijbehorende JavaScript- of TypeScript-code. Je organiseert functies in aparte mappen met specifieke bestandsstructuren. Elke functie heeft één enkele trigger die de uitvoering start en kan ook bindings hebben, wat declaratieve verbindingen zijn met andere services voor het lezen van invoerdata of het schrijven van uitvoergegevens. Voor meer informatie, zie Triggers en bindingen.

In het v3-model doet u:

  • Definieer triggers en bindings in een function.json bestand. Gebruik direction: "in" voor inputs en direction: "out" voor outputs.
  • Benader de triggerinvoer als het tweede argument van je handler, of lees deze uit context.bindings.
  • Stel outputs in door waarden toe te wijzen aan context.bindings (bijvoorbeeld context.bindings.outputQueue). Voor HTTP gebruik context.res.
  • TypeScript-projecten vereisen een scriptFile eigenschap in function.json die verwijst naar het gecompileerde JavaScript-bestand.
  • Elke functie heeft precies één trigger, maar kan meerdere input- en outputbindings hebben.
  • Je kunt gegevens cachen in globale variabelen voor hergebruik tussen aanroepen, maar ga er niet van uit dat deze toestand behouden blijft. De runtime kan je werknemer op elk moment recyclen.

Examples

Hier volgt een eenvoudige functie die reageert op een HTTP-aanvraag:

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}!` };
    }
});

Het volgende niet-HTTP-voorbeeld gebruikt een timer-trigger:

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());
  }
});

Het volgende voorbeeld toont een HTTP-trigger met een queue-uitvoerbinding:

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 } };
  }
});

Hier volgt een eenvoudige functie die reageert op een HTTP-aanvraag:

{
  "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}!`
    };
};

Het volgende niet-HTTP-voorbeeld gebruikt een timer-trigger:

{
  "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());
};

Het volgende voorbeeld toont een HTTP-trigger met een queue-uitvoerbinding:

{
  "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 }
    };
};

Uw functie-app bouwen

Deze sectie behandelt de essentiële componenten voor het maken en structureren van je Node-functieapp, waaronder de @azure/functions bibliotheek, projectstructuur en pakketbeheer.

De @azure/functions bibliotheek

De @azure/functions TypeScript/JavaScript-bibliotheek biedt de kerntypen en functies die je gebruikt om met de Azure Functions-runtime te communiceren. Als u alle beschikbare typen en methoden wilt zien, gaat u naar de @azure/functions API.

Uw functiecode kan het volgende gebruiken @azure/functions :

  • Registreer functies en definieer triggers (v4-model).
  • Toegang tot sterk getypeerde triggerinvoergegevens (bijvoorbeeld HttpRequest, Timer).
  • Maak getypeerde uitvoerwaarden aan (zoals HttpResponseInit).
  • Werken met door de runtime geleverde context en bindingsgegevens.

Als je het in je app gebruikt @azure/functions , neem het dan op in je projectafhankelijkheden:

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

Notitie

De @azure/functions bibliotheek definieert het programmeeroppervlak voor Node.js Azure Functions, maar het is geen algemene SDK. Gebruik deze functie specifiek voor het ontwerpen en uitvoeren van functies binnen de Azure Functions-runtime.

TypeScript-configuratie

Voor de beste TypeScript-ontwikkelingservaring, zorg ervoor dat je tsconfig.json de juiste configuratie bevat:

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

Mapstructuur

Een JavaScript-project vereist de mappenstructuur zoals weergegeven in het volgende voorbeeld:

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

De hoofdprojectmap, <project_root>, kan de volgende bestanden bevatten:

  • .vscode/: (optioneel) Bevat de opgeslagen Visual Studio Code-configuratie. Zie Visual Studio Code settings voor meer informatie.
  • myFirstFunction/function.json: bevat configuratie voor de trigger, invoer en uitvoer van de functie. De naam van de map bepaalt de naam van uw functie.
  • myFirstFunction/index.js: Slaat uw functiecode op. Zie door scriptFile te gebruiken om dit standaardbestandspad te wijzigen.
  • .funcignore: (Optioneel) Declareert bestanden die niet mogen worden gepubliceerd naar Azure. Meestal bevat dit bestand .vscode/ om je editor-instelling te negeren, test/ om testgevallen te negeren, en local.settings.json om lokale app-instellingen te voorkomen dat ze worden gepubliceerd.
  • host.json: bevat configuratieopties die van invloed zijn op alle functies in een exemplaar van een functie-app. Dit bestand wordt gepubliceerd in Azure. Niet alle opties worden ondersteund bij lokaal uitvoeren. Zie host.json voor meer informatie.
  • local.settings.json: wordt gebruikt om app-instellingen en verbindingsreeksen op te slaan bij lokale uitvoering. Dit bestand wordt niet gepubliceerd naar Azure. Zie local.settings.file voor meer informatie.
  • package.json: Bevat configuratieopties zoals een lijst van pakketafhankelijkheden, het belangrijkste toegangspunt en scripts.

Een JavaScript-project volgt de aanbevolen mapstructuur in het volgende voorbeeld:

<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

De hoofdprojectmap, <project_root>, kan de volgende bestanden bevatten:

  • .vscode/: (optioneel) Bevat de opgeslagen Visual Studio Code-configuratie. Zie Visual Studio Code settings voor meer informatie.
  • src/functions/: de standaardlocatie voor alle functies en de bijbehorende triggers en bindingen.
  • test/: (optioneel) Bevat de testcases van uw functie-app.
  • .funcignore: (Optioneel) Declareert bestanden die niet mogen worden gepubliceerd naar Azure. Meestal bevat dit bestand .vscode/ om je editor-instelling te negeren, test/ om testgevallen te negeren, en local.settings.json om lokale app-instellingen te voorkomen dat ze worden gepubliceerd.
  • host.json: bevat configuratieopties die van invloed zijn op alle functies in een exemplaar van een functie-app. Dit bestand wordt gepubliceerd in Azure. Niet alle opties worden ondersteund bij lokaal uitvoeren. Zie host.json voor meer informatie.
  • local.settings.json: wordt gebruikt om app-instellingen en verbindingsreeksen op te slaan bij lokale uitvoering. Dit bestand wordt niet gepubliceerd naar Azure. Zie local.settings.file voor meer informatie.
  • package.json: Bevat configuratieopties zoals een lijst van pakketafhankelijkheden, het belangrijkste toegangspunt en scripts.

Pakketbeheer

Effectief pakketbeheer is cruciaal voor Node.js Azure Functions projecten. Deze sectie behandelt afhankelijkheidsbeheer, pakketconfiguratie en best practices voor het onderhouden van afhankelijkheden van je functie-app.

Beheer van afhankelijkheden

Alle Node.js Azure Functions projecten gebruiken npm voor pakketbeheer. Je bestand definieert package.json de projectconfiguratie, afhankelijkheden en scripts die nodig zijn om je functies te bouwen en uit te voeren.

Essentiële package.json structuur:

{
  "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 versus ontwikkelingsafhankelijkheden

Scheid je afhankelijkheden op de juiste manier:

Runtime-afhankelijkheden (dependencies):

  • @azure/functions: De kernbibliotheek van Azure Functions
  • Business logic libraries (lodash, axios en vergelijkbare pakketten)
  • Databasedrivers (mongodb, mssql en vergelijkbare pakketten)
  • Azure SDK pakketten (@azure/storage-blob, @azure/cosmos, en vergelijkbare pakketten)

Ontwikkelingsafhankelijkheden (devDependencies):

  • TypeScript-compiler en typedefinities
  • Testraamwerken (Jest, Mocha)
  • Bouwgereedschappen en linters
  • Azure Functions Core Tools (voor lokale ontwikkeling)

TypeScript-specifieke pakketten

Voor TypeScript-projecten neem deze essentiële ontwikkelingsafhankelijkheden op:

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

Beveiliging en updates

Werk uw afhankelijkheden regelmatig bij om beveiligingslekken aan te pakken:

# Check for outdated packages
npm outdated

# Update packages
npm update

# Audit for security issues
npm audit
npm audit fix

Uitvoeren en debuggen

Deze sectie behandelt lokale ontwikkeling, debuggingtechnieken en teststrategieën voor Node.js Azure Functions.

Instelling van lokale ontwikkeling

Voorwaarden:

Installatiestappen:

  1. Afhankelijkheden installeren:

    npm install
    
  2. Bouw TypeScript-projecten:

    npm run build
    
  3. Start de lokale runtime:

    npm start
    # or directly:
    func start
    

Omgevingsconfiguratie

Configureer je lokale ontwikkelomgeving met behulp van 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
  }
}

foutopsporing

Visual Studio Code debugging:

Maak .vscode/launch.json:

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

Maak .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}"
      }
    }
  ]
}

Opdrachtregel-debugging:

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

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

Deployment

Deze sectie behandelt implementatiestrategieën, CI/CD-integratie en productiebest practices voor Node.js Azure Functions.

Implementatiemethoden

1. Visual Studio Code implementatie:

  • Installeer de Azure Functions-extensie.
  • Klik met de rechtermuisknop op je functie-app in het Azure-paneel.
  • Selecteer Deploy to Function App.

2. Azure Functions 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. Azure CLI deployment:

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

Productieconfiguratie

Application settings in Azure:

Configureer omgevingsvariabelen voor productie:

  • WEBSITE_NODE_DEFAULT_VERSION: Ingesteld op ~18 of ~20.
  • FUNCTIONS_WORKER_RUNTIME: Ingesteld op node.
  • Verbindingsstrings en API-sleutels als veilige app-instellingen.
  • NODE_ENV: Ingesteld op production.

Triggers en bindingen

Azure Functions gebruikt triggers om de uitvoering van functies te starten en bindingen om uw code te verbinden met andere services, zoals opslag, wachtrijen en databases. In het Node.js programmeermodel declareer je bindings verschillend afhankelijk van je modelversie.

Er bestaan twee hoofdtypen bindingen:

  • Triggers (invoer waarmee de functie wordt gestart)
  • Invoer en uitvoer (extra gegevensbronnen of bestemmingen)

Zie Triggers en bindingen in Azure Functions voor meer informatie over de beschikbare triggers en bindingen.

Voorbeeld: Timertrigger met Blob-invoer

Deze functie wordt elke 10 minuten geactiveerd, leest uit een Blob met extra inputs en registreert de inhoud van de 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}`);
    }
});

Deze functie wordt elke 10 minuten geactiveerd, leest uit een Blob door gebruik te maken van bindingsconfiguratie en logt de inhoud van de 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}`);
};

Voorbeeld: HTTP-trigger met wachtrij-uitvoer

Deze functie wordt geactiveerd op een HTTP-verzoek, schrijft een bericht naar een opslagwachtrij en geeft een HTTP-antwoord terug.

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.`
        };
    }
});

Deze functie wordt geactiveerd op een HTTP-verzoek, schrijft een bericht naar een opslagwachtrij en geeft een HTTP-antwoord terug.

{
  "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.`
    };
};

De app, triggeren inputobjecten die door de module worden geëxporteerd, output bieden typespecifieke methoden voor de @azure/functions meeste typen. Voor alle typen die niet worden ondersteund, wordt een generic methode opgegeven waarmee u de configuratie handmatig kunt opgeven. De generic methode kan ook worden gebruikt als u de standaardinstellingen van een typespecifieke methode wilt wijzigen.

Het volgende voorbeeld is een eenvoudige door HTTP geactiveerde functie met behulp van algemene methoden in plaats van typespecifieke methoden.

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!` };
  },
});

N/A (no changes needed if it is a technical placeholder or coding element)

Aanroepcontext

Elke aanroep van je functie ontvangt een aanroepobject context . Gebruik dit object om invoer te lezen, uitvoer in te stellen, naar logs te schrijven en toegang te krijgen tot diverse metadata. In het v3-model geef je altijd het contextobject als eerste argument door aan je handler.

Het context object bevat de volgende eigenschappen:

Eigenschap Beschrijving
invocationId De ID van de huidige functieaanroep.
executionContext Bekijk de uitvoeringscontext.
bindings Zie bindingen.
bindingData Metadata over de triggerinvoer voor deze aanroep, exclusief de waarde zelf. Een Event Hub-trigger heeft bijvoorbeeld een enqueuedTimeUtc eigenschap.
traceContext De context voor gedistribueerde tracering. Zie Trace Context voor meer informatie.
bindingDefinitions De configuratie van uw invoer en uitvoer, zoals gedefinieerd in function.json.
req Zie http-aanvraag.
res Zie http-antwoord.

context.executionContext

Het context.executionContext-object heeft de volgende eigenschappen:

Eigenschap Beschrijving
invocationId De ID van de huidige functieaanroep.
functionName De naam van de functie die je inroept. De naam van de map met het function.json bestand bepaalt de naam van de functie.
functionDirectory De map met het function.json bestand.
retryContext Zie herhalingscontext.

context.executionContext.retryContext

Het context.executionContext.retryContext-object heeft de volgende eigenschappen:

Eigenschap Beschrijving
retryCount Een getal dat de huidige poging voor opnieuw proberen aangeeft.
maxRetryCount Maximum aantal keren dat een uitvoering opnieuw wordt geprobeerd. Een waarde van -1 betekent om het voor onbepaalde tijd opnieuw te proberen.
exception Uitzondering die de nieuwe poging heeft veroorzaakt.

context.bindingen

Gebruik het context.bindings object om invoer te lezen of uitgangen in te stellen. Het volgende voorbeeld is een storage queue-trigger die wordt gebruikt context.bindings om een storage blob-invoer te kopiëren naar een storage blob-output. De inhoud van het wachtrijbericht vervangt {queueTrigger} als de bestandsnaam om te kopiëren, met behulp van een bindingsexpressie.

{
    "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.afgesloten

De context.done methode is afgeschaft. Voordat Azure Functions asynchrone functies ondersteunde, gaf je aan dat je functie klaar was door aan te roepencontext.done():

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

Verwijder de aanroep naar context.done(). Markeer je functie als asynchroon zodat hij een belofte teruggeeft (ook al doe je niets await ). Zodra uw functie is voltooid (met andere woorden, de geretourneerde belofte wordt afgehandeld), weet het v3-model dat uw functie is afgerond.

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

Elke aanroep van je functie ontvangt een aanroepobject context . Dit object bevat informatie over je aanroep en methoden voor logging. In het v4-model geef je het context object meestal als tweede argument door aan je handler.

De InvocationContext klasse bevat de volgende eigenschappen:

Eigenschap Beschrijving
invocationId De ID van de huidige functieaanroep.
functionName De naam van de functie.
extraInputs Wordt gebruikt om de waarden van extra invoer op te halen. Zie extra invoer en uitvoer voor meer informatie.
extraOutputs Wordt gebruikt om de waarden van extra uitvoer in te stellen. Zie extra invoer en uitvoer voor meer informatie.
retryContext Zie herhalingscontext.
traceContext De context voor gedistribueerde tracering. Zie Trace Context voor meer informatie.
triggerMetadata Metagegevens over de triggerinvoer voor deze aanroep, niet inclusief de waarde zelf. Een Event Hub-trigger heeft bijvoorbeeld een enqueuedTimeUtc eigenschap.
options De opties die worden gebruikt bij het registreren van de functie, nadat ze zijn gevalideerd en de standaardinstellingen expliciet zijn gespecificeerd.

Opnieuw probeercontext

Het retryContext-object heeft de volgende eigenschappen:

Eigenschap Beschrijving
retryCount Een getal dat de huidige poging voor opnieuw proberen aangeeft.
maxRetryCount Maximum aantal keren dat een uitvoering opnieuw wordt geprobeerd. Een waarde van -1 betekent om het voor onbepaalde tijd opnieuw te proberen.
exception Uitzondering die de nieuwe poging heeft veroorzaakt.

Zie retry-policies voor meer informatie.

Logboekregistratie

In Azure Functions gebruik context.log() je om logs te schrijven. Azure Functions integreert met Azure-toepassing Insights om uw functie-app-logboeken beter vast te leggen. Application Insights, onderdeel van Azure Monitor, biedt faciliteiten voor verzameling, visuele rendering en analyse van zowel toepassingslogboeken als traceringsuitvoer. Zie monitoring Azure Functions voor meer informatie.

Notitie

Als je de alternatieve Node.js console.log methode gebruikt, worden de logs op app-niveau bijgehouden maar niet gekoppeld aan een specifieke functie. Gebruik context het voor logging in plaats van console zodat alle logs aan een specifieke functie gekoppeld zijn.

In het volgende voorbeeld wordt een logboek op het standaardniveau 'informatie' geschreven, inclusief de aanroep-id:

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

Logboekniveaus

Naast de standaardmethode context.log kun je de volgende methoden gebruiken om logs op specifieke niveaus te schrijven:

Wijze Beschrijving
context.log.error() Hiermee schrijft u een gebeurtenis op foutniveau naar de logboeken.
context.log.warn() Hiermee schrijft u een gebeurtenis op waarschuwingsniveau naar de logboeken.
context.log.info() Hiermee schrijft u een gebeurtenis op informatieniveau naar de logboeken.
context.log.verbose() Hiermee schrijft u een gebeurtenis op traceringsniveau naar de logboeken.
Wijze Beschrijving
context.trace() Hiermee schrijft u een gebeurtenis op traceringsniveau naar de logboeken.
context.debug() Hiermee schrijft u een gebeurtenis op foutopsporingsniveau naar de logboeken.
context.info() Hiermee schrijft u een gebeurtenis op informatieniveau naar de logboeken.
context.warn() Hiermee schrijft u een gebeurtenis op waarschuwingsniveau naar de logboeken.
context.error() Hiermee schrijft u een gebeurtenis op foutniveau naar de logboeken.

Logboekniveau configureren

Functions stelt je in staat het drempelniveau te definiëren voor het volgen en bekijken van logs. Als u de drempelwaarde wilt instellen, gebruikt u de logging.logLevel eigenschap in het host.json bestand. Met deze eigenschap kun je een standaardniveau voor alle functies definiëren of een drempel voor elke individuele functie. Zie De bewaking configureren voor Azure Functions voor meer informatie.

Aangepaste gegevens bijhouden

Standaard schrijft Azure Functions uitvoer als traceringen naar Application Insights. Voor meer controle gebruik je de Application Insights Node.js SDK om aangepaste logs, metrics en afhankelijkheden naar je Application Insights-instantie te sturen.

Notitie

Methoden in de Application Insights Node.js SDK kunnen na verloop van tijd veranderen. Er kunnen kleine syntaxisverschillen zijn ten opzichte van de voorbeelden die hier worden getoond. Zie de Application Insights Node.js SDK-documentatie voor de nieuwste voorbeelden van API-gebruik.

Voor gedistribueerd traceren in het Node.js v4 programmeermodel, gebruik het @azure/functions-opentelemetry-instrumentation pakket in plaats van de Application Insights SDK. Dit pakket biedt automatische instrumentatie op basis van OpenTelemetry voor Azure Functions. Zie voor meer informatie de GitHub-repository OpenTelemetry Azure Functions Instrumentation voor Node.js.

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,
  });
};

Met tagOverrides de parameter wordt de operation_Id aanroep-id van de functie ingesteld. Met deze instelling kun je alle automatisch gegenereerde en aangepaste logs voor een bepaalde functie-aanroep correleren.

HTTP-triggers

HTTP- en webhooktriggers gebruiken aanvraag- en antwoordobjecten om HTTP-berichten weer te geven.

HTTP- en webhooktriggers gebruiken HttpRequest en HttpResponse objecten om HTTP-berichten weer te geven. De klassen vertegenwoordigen een subset van de ophaalstandaard met behulp van het pakket van undici Node.js.

HTTP-aanvraag

Toegang tot het verzoek op verschillende manieren:

  • Als tweede argument voor uw functie:

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

  • Vanuit de context.req eigenschap:

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

  • Uit de benoemde invoerbindingen: Deze optie werkt hetzelfde als elke niet-HTTP binding. De bindingsnaam in function.json moet overeenkomen met de sleutel op context.bindings, of 'request1' in het volgende voorbeeld.

    {
      "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}"`);
    

Het HttpRequest-object heeft de volgende eigenschappen:

Eigenschap Typologie Beschrijving
method string Http-aanvraagmethode die wordt gebruikt om deze functie aan te roepen.
url string Aanvraag-URL.
headers Record<string, string> HTTP-aanvraagheaders. Dit object is hoofdlettergevoelig. Gebruik request.getHeader('header-name') in plaats daarvan, wat niet hoofdlettergevoelig is.
query Record<string, string> Queryreeks-parameter-sleutels en -waarden uit de URL.
params Record<string, string> Routeparameter sleutels en -waarden.
user HttpRequestUser \| null Object dat de aangemelde gebruiker vertegenwoordigt, hetzij via Functions-verificatie, SWA-verificatie of null wanneer een dergelijke gebruiker niet is aangemeld.
body Buffer \| string \| any Als het mediatype 'application/octet-stream' of 'multipart/*' is, body is dit een buffer. Als de waarde een JSON-tekenreeks is die kan worden geparseerd, body is het geparseerde object. Anders is body een tekenreeks.
rawBody string De inhoud als een string. Ondanks de naam retourneert deze eigenschap geen buffer.
bufferBody Buffer Het lichaam als buffer.

Je kunt het verzoek benaderen als eerste argument van je handler voor een door HTTP geactiveerde functie.

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

Het HttpRequest-object heeft de volgende eigenschappen:

Eigenschap Typologie Beschrijving
method string Http-aanvraagmethode die wordt gebruikt om deze functie aan te roepen.
url string Aanvraag-URL.
headers Headers HTTP-aanvraagheaders.
query URLSearchParams Queryreeks-parameter-sleutels en -waarden uit de URL.
params Record<string, string> Routeparameter sleutels en -waarden.
user HttpRequestUser \| null Object dat de aangemelde gebruiker vertegenwoordigt, hetzij via Functions-verificatie, SWA-verificatie of null wanneer een dergelijke gebruiker niet is aangemeld.
body ReadableStream \| null Body als leesbare stream.
bodyUsed boolean Een Booleaanse waarde die aangeeft of de hoofdtekst al is gelezen.

Om toegang te krijgen tot het lichaam van een verzoek of antwoord, gebruik je de volgende methoden:

Wijze Retourtype
arrayBuffer() Promise<ArrayBuffer>
blob() Promise<Blob>
formData() Promise<FormData>
json() Promise<unknown>
text() Promise<string>

Notitie

Je kunt de lichaamsfuncties maar één keer uitvoeren. Latere aanroepen worden opgelost met lege strings of ArrayBuffers.

HTTP-antwoord

Je kunt de respons op verschillende manieren instellen. U kunt bijvoorbeeld het volgende gebruiken:

  • Stel de context.res eigenschap in:

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

  • Retourneer het antwoord: Als uw functie asynchroon is en u de bindingsnaam $return instelt in uw function.json, kunt u het antwoord rechtstreeks retourneren in plaats van deze contextin te stellen.

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

  • Stel de benoemde uitvoerbinding in: Deze optie werkt hetzelfde als elke niet-HTTP binding. De naam van de binding moet function.json overeenkomen met de sleutel in context.bindings, of 'response1' in het volgende voorbeeld:

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

  • Aanroep context.res.send(): deze optie is afgeschaft. Het roept impliciet aan context.done() en je kunt het niet gebruiken in een asynchrone functie.

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

Als u een nieuw object maakt bij het instellen van het antwoord, moet dat object overeenkomen met de HttpResponseSimple interface, die de volgende eigenschappen heeft:

Eigenschap Typologie Beschrijving
headers Record<string, string> (optioneel) HTTP-antwoordheaders.
cookies Cookie[] (optioneel) HTTP-antwoordcookies.
body any (optioneel) HTTP-antwoordlichaam.
statusCode number (optioneel) HTTP-antwoordstatuscode. Als dit niet is ingesteld, wordt standaard ingesteld op 200.
status number (optioneel) Hetzelfde als statusCode. Deze eigenschap wordt genegeerd als statusCode is ingesteld.

U kunt het context.res object ook wijzigen zonder het te overschrijven. Het standaardobject context.res maakt gebruik van de HttpResponseFull interface, die naast de HttpResponseSimple eigenschappen de volgende methoden ondersteunt:

Wijze Beschrijving
status() Hiermee stelt u de status in.
setHeader() Hiermee stelt u een koptekstveld in. OPMERKING:res.set() En res.header() ze worden ook ondersteund en doen hetzelfde.
getHeader() Krijgt een headerveld. OPMERKING:res.get() Wordt ook ondersteund en doet hetzelfde.
removeHeader() Hiermee verwijdert u een koptekst.
type() Hiermee stelt u de header 'Content-Type' in.
send() Deze methode is afgeschaft. Het stelt de hoofdtekst in en roept context.done() aan om aan te geven dat een synchronisatiefunctie is voltooid. OPMERKING:res.end() Wordt ook ondersteund en doet hetzelfde.
sendStatus() Deze methode is afgeschaft. Hiermee stelt u de statuscode en aanroepen context.done() in om aan te geven dat een synchronisatiefunctie is voltooid.
json() Deze methode is afgeschaft. Hiermee stelt u het 'inhoudstype' in op 'application/json', stelt u de hoofdtekst in en roept u context.done() aan om aan te geven dat een synchronisatiefunctie is voltooid.

Je kunt de respons op verschillende manieren instellen. U kunt bijvoorbeeld het volgende gebruiken:

  • Een eenvoudige interface met type HttpResponseInit: Deze optie is de meest beknopte manier om antwoorden terug te geven.

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

De HttpResponseInit interface heeft de volgende eigenschappen:

Eigenschap Typologie Beschrijving
body BodyInit (optioneel) Http-antwoordtekst als een van ArrayBuffer, , AsyncIterable<Uint8Array>, Blob, FormData, Iterable<Uint8Array>, , NodeJS.ArrayBufferView, , URLSearchParams, of nullstring.
jsonBody any (optioneel) Een http-antwoordtekst die kan worden geseriialiseerd met JSON. Indien ingesteld, wordt de HttpResponseInit.body eigenschap genegeerd ten gunste van deze eigenschap.
status number (optioneel) HTTP-antwoordstatuscode. Als dit niet is ingesteld, wordt standaard ingesteld op 200.
headers HeadersInit (optioneel) HTTP-antwoordheaders.
cookies Cookie[] (optioneel) HTTP-antwoordcookies.
  • Als klasse met type HttpResponse: deze optie biedt helpermethoden voor het lezen en wijzigen van verschillende delen van het antwoord, zoals de headers.

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

De HttpResponse klasse accepteert een optioneel HttpResponseInit als argument voor de constructor en heeft de volgende eigenschappen:

Eigenschap Typologie Beschrijving
status number HTTP-antwoordstatuscode.
headers Headers HTTP-antwoordheaders.
cookies Cookie[] HTTP-antwoordcookies.
body ReadableStream | null Body als leesbare stream.
bodyUsed boolean Een Booleaanse waarde die aangeeft of de hoofdtekst al is gelezen.

HTTP-stromen

HTTP-streams is een functie waarmee u gemakkelijker grote gegevens kunt verwerken, OpenAI-antwoorden kunt streamen, dynamische inhoud kunt leveren en andere http-kernscenario's kunt ondersteunen. Hiermee kunt u aanvragen naar en antwoorden van HTTP-eindpunten streamen in uw Node.js functie-app. Gebruik HTTP-streams in scenario's waarin uw app realtime uitwisseling en interactie tussen client en server via HTTP vereist. U kunt ook HTTP-streams gebruiken om de beste prestaties en betrouwbaarheid voor uw apps te verkrijgen wanneer u HTTP gebruikt.

Belangrijk

HTTP-streams worden niet ondersteund in het v3-model. Voer een upgrade uit naar het v4-model om de HTTP-streamingfunctie te gebruiken. De bestaande HttpRequest typen HttpResponse in het programmeermodel v4 ondersteunen al verschillende manieren om de berichttekst te verwerken, inclusief als een stroom.

Vereisten

Streams inschakelen

Gebruik deze stappen om HTTP-streams in te schakelen in uw functie-app in Azure en in uw lokale projecten:

  1. Als u van plan bent grote hoeveelheden gegevens te streamen, wijzigt u de instelling FUNCTIONS_REQUEST_BODY_SIZE_LIMIT in Azure. De standaard toegestane maximale grootte van de requestbody is 104857600, wat uw verzoeken beperkt tot ongeveer 100 MB.

  2. Voor lokale ontwikkeling voegt u ook toe FUNCTIONS_REQUEST_BODY_SIZE_LIMIT aan het local.settings.json-bestand.

  3. Voeg de volgende code toe aan uw app in elk bestand dat is opgenomen in het hoofdveld.

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

Stream-voorbeelden

Het volgende voorbeeld toont een HTTP-getriggerde functie die gegevens ontvangt via een HTTP POST-verzoek. De functie streamt deze gegevens naar een gespecificeerd uitvoerbestand:

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!' };
    },
});

Het volgende voorbeeld toont een HTTP-getriggerde functie die de inhoud van een bestand streamt als antwoord op binnenkomende HTTP GET-verzoeken:

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 };
    },
});

Voor een kant-en-klare voorbeeldapp die streams gebruikt, bekijk dit voorbeeld op GitHub.

Overwegingen voor streaming

  • Gebruikt request.body om het meeste voordeel te halen uit het gebruik van streams. Je kunt nog steeds methoden gebruiken zoals request.text(), die altijd de hoofdtekst als tekenreeks retourneren.

Haken

Het v3-model ondersteunt geen hooks. Voer een upgrade uit naar het v4-model om hooks te gebruiken.

Gebruik een hook om code uit te voeren op verschillende punten in de levenscyclus van Azure Functions. De volgorde waarin je hooks registreert bepaalt in welke volgorde ze worden uitgevoerd. Je kunt hooks registreren vanuit elk bestand in je app. Er bestaan twee scopes van hooks: "app"-niveau en "invocation"-niveau.

Aanroephaken

Invocation-hooks worden één keer per aanroep van uw functie uitgevoerd. Een preInvocation hook draait voordat de functie wordt uitgevoerd, en een postInvocation hook wordt uitgevoerd nadat de functie is uitgevoerd. Standaard wordt je hook uitgevoerd voor alle triggertypes, maar je kunt ook filteren op type. In het volgende voorbeeld ziet u hoe u een aanroephook registreert en filtert op triggertype:

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']
});

Het eerste argument voor de haakhandler is een contextobject dat specifiek is voor dat haaktype.

Het PreInvocationContext-object heeft de volgende eigenschappen:

Eigenschap Beschrijving
inputs De argumenten die je doorgeeft aan de aanroep.
functionHandler De handler voor de functieaanroep. Wijzigingen in deze waarde zijn van invloed op de functie zelf.
invocationContext Het aanroepcontext-object dat aan de functie is doorgegeven.
hookData De aanbevolen plek voor het opslaan en delen van gegevens tussen hooks binnen dezelfde context. Gebruik een unieke eigenschapsnaam zodat deze niet conflicteert met de data van andere hooks.

Het PostInvocationContext-object heeft de volgende eigenschappen:

Eigenschap Beschrijving
inputs De argumenten die je doorgeeft aan de aanroep.
result Het resultaat van de functie. Wijzigingen in deze waarde zijn van invloed op het algehele resultaat van de functie.
error De fout die door de functie is opgeworpen, of null/undefined als er geen fout is. Wijzigingen in deze waarde zijn van invloed op het algehele resultaat van de functie.
invocationContext Het aanroepcontext-object dat aan de functie is doorgegeven.
hookData De aanbevolen plek voor het opslaan en delen van gegevens tussen hooks binnen dezelfde context. Gebruik een unieke eigenschapsnaam zodat deze niet conflicteert met de data van andere hooks.

Apphooks

De runtime voert app-hooks één keer per instantie van je app uit. Het voert appStart hooks uit tijdens het opstarten en appTerminate hooks tijdens het afsluiten. Afsluitingshooks van apps hebben beperkte tijd om uitgevoerd te worden en worden niet in alle scenario's uitgevoerd.

De Azure Functions-runtime ondersteunt momenteel geen contextlogboeken buiten een aanroep. Gebruik het Npm-pakket van Application Insights om gegevens te registreren tijdens hooks op app-niveau.

In het volgende voorbeeld worden app-hooks geregistreerd:

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 }));
});

Het eerste argument voor de haakhandler is een contextobject dat specifiek is voor dat haaktype.

Het AppStartContext object heeft de volgende eigenschap:

Eigenschap Beschrijving
hookData De aanbevolen plek voor het opslaan en delen van gegevens tussen hooks binnen dezelfde context. Gebruik een unieke eigenschapsnaam zodat deze niet conflicteert met de data van andere hooks.

Het AppTerminateContext object heeft de volgende eigenschap:

Eigenschap Beschrijving
hookData De aanbevolen plek voor het opslaan en delen van gegevens tussen hooks binnen dezelfde context. Gebruik een unieke eigenschapsnaam zodat deze niet conflicteert met de data van andere hooks.

Best practices voor haak

Wanneer je hooks gebruikt in je Azure Functions, houd dan rekening met deze best practices:

Prestatie-overwegingen

  • Houd de uitvoeringstijd van de hook minimaal om de functieprestaties niet te beïnvloeden.
  • Gebruik waar mogelijk asynchrone bewerkingen om blokkering te voorkomen.
  • Houd rekening met de overhead van hooks bij het verwerken van verzoeken met een hoog volume.

Foutafhandeling

  • Zorg altijd dat je fouten goed behandelt in je hooks.
  • Laat haakstoringen geen functiestoringen veroorzaken, tenzij het absoluut noodzakelijk is.
  • Registreer hook-fouten correct voor foutopsporing.

Delen van gegevens

  • Gebruik hookData om informatie te delen tussen pre- en post-aanroephooks.
  • Gebruik unieke eigendomsnamen om conflicten met andere hooks te voorkomen.
  • Verwijder hook-data wanneer ze niet meer nodig zijn om geheugenlekken te voorkomen.

Filteren

  • Gebruik triggertype-filtering om ervoor te zorgen dat hooks alleen voor relevante functies draaien.
  • Wees specifiek met je filters om de prestaties te optimaliseren.

Schalen en gelijktijdigheid

Standaard controleert Azure Functions de belasting van uw toepassing automatisch en worden er zo nodig meer hostexemplaren voor Node.js gemaakt. Azure Functions gebruikt ingebouwde (niet door de gebruiker configureerbare) drempels voor verschillende triggertypes om te bepalen wanneer instanties worden toegevoegd, zoals de leeftijd van berichten en de wachtrijgrootte voor QueueTrigger. Zie Hoe de Verbruiks- en Premium-abonnementen werken voor meer informatie.

Dit schaalgedrag is voldoende voor veel Node.js toepassingen. Voor CPU-afhankelijke toepassingen kunt u de prestaties verder verbeteren door gebruik te maken van werkprocessen in meerdere talen. U kunt het aantal werkprocessen per host verhogen van de standaardwaarde van 1 tot maximaal 10 met behulp van de FUNCTIONS_WORKER_PROCESS_COUNT toepassingsinstelling. Azure Functions probeert vervolgens gelijktijdige functieaanroepen over deze werknemers gelijkmatig te verdelen. Dit gedrag maakt het minder waarschijnlijk dat een CPU-intensieve functie voorkomt dat andere functies worden uitgevoerd. De instelling is van toepassing op elke host die Azure Functions maakt bij het uitschalen van uw toepassing om aan de vraag te voldoen.

Waarschuwing

Gebruik de FUNCTIONS_WORKER_PROCESS_COUNT instelling voorzichtig. Meerdere processen die in hetzelfde exemplaar worden uitgevoerd, kunnen leiden tot onvoorspelbaar gedrag en kunnen de laadtijden van de functie verhogen. Als je deze instelling gebruikt, kan het draaien vanuit een pakketbestand deze nadelen compenseren.

Node-versie

U kunt de huidige versie die door de runtime wordt gebruikt zien door process.version vanuit een functie te loggen. Zie supported versions voor een lijst met Node.js versies die door elk programmeermodel worden ondersteund.

De Node-versie instellen

De manier waarop u uw Node.js-versie bijwerken, is afhankelijk van het besturingssysteem waarop uw functie-app wordt uitgevoerd.

Wanneer het op Windows draait, stel je de Node.js versie in via de WEBSITE_NODE_DEFAULT_VERSION applicatie-instelling. Werk deze instelling bij door de Azure CLI te gebruiken of in het Azure-portaal.

Zie Ondersteunde versies voor meer informatie over Node.js versies.

Voordat u uw Node.js-versie bijwerken, moet u ervoor zorgen dat uw functie-app wordt uitgevoerd op de nieuwste versie van de Azure Functions runtime. Zie Migrate-apps van Azure Functions versie 3.x naar versie 4.x als u uw runtime-versie wilt upgraden.

Voer de opdracht Azure CLI az functionapp config appsettings set uit om de Node.js-versie bij te werken voor uw functie-app die wordt uitgevoerd op Windows:

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

Dit commando stelt de WEBSITE_NODE_DEFAULT_VERSION applicatie-instelling in op de ondersteunde LTS-versie ~22.

Nadat je wijzigingen hebt gedaan, start je functie-app opnieuw op. Zie het ondersteuningsbeleid voor Language Runtime voor meer informatie over de ondersteuning van Functions voor Node.js.

Omgevingsvariabelen

Gebruik omgevingsvariabelen om operationele geheimen te beheren, zoals verbindingsstrings, sleutels en eindpunten. Gebruik ze ook voor omgevingsinstellingen, zoals het profileren van variabelen. Voeg omgevingsvariabelen toe in zowel je lokale als cloudomgevingen en gebruik deze via process.env je functiecode.

In het volgende voorbeeld wordt de WEBSITE_SITE_NAME omgevingsvariabele in een logboek opgeslagen:

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"]}`);
}

In de lokale ontwikkelomgeving

Wanneer u lokaal uitvoert, bevat uw functions-project een local.settings.json bestand waarin u uw omgevingsvariabelen opslaat in het Values object.

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

In Azure cloudomgeving

Wanneer u in Azure uitvoert, kunt u met de functie-app Application-instellingen, zoals serviceverbindingsreeksen, instellen en gebruiken en deze instellingen weergeven als omgevingsvariabelen tijdens de uitvoering.

Er zijn verschillende manieren waarop u instellingen van een functie app kunt toevoegen, bijwerken en verwijderen:

Voor wijzigingen in de instellingen van de functie-app moet uw functie-app opnieuw worden gestart.

Omgevingsvariabelen voor workers

Node.js heeft verschillende Functions-omgevingsvariabelen die specifiek voor hem zijn:

languageWorkers__node__arguments

Gebruik deze instelling om aangepaste argumenten te specificeren wanneer je je Node.js start. Meestal gebruik je het lokaal om de worker in debugmodus te starten, maar je kunt het ook in Azure gebruiken als je aangepaste argumenten nodig hebt.

Waarschuwing

Vermijd indien mogelijk gebruik languageWorkers__node__arguments in Azure, omdat dit de koude starttijden negatief kan beïnvloeden. In plaats van voorverwarmde werkprocessen te gebruiken, moet de runtime een nieuw werkproces helemaal opnieuw opstarten met je aangepaste argumenten.

logboekbeheerlogLevelWerknemer

Gebruik deze instelling om het standaardlogniveau voor Node.js-specifieke werkerlogs aan te passen. Standaard worden alleen waarschuwings- of foutlogboeken weergegeven, maar u kunt deze instellen op information of debug om problemen met de Node.js-worker op te sporen. Zie Logboekniveaus configureren voor meer informatie.

ECMAScript-modules (voorbeeld)

Notitie

ECMAScript-modules zijn momenteel een previewfunctie in Node.js 14 of hoger in Azure Functions.

ECMAScript-modules (ES-modules ) zijn het nieuwe officiële standaardmodulesysteem voor Node.js. Tot nu toe gebruiken de codevoorbeelden in dit artikel de CommonJS-syntaxis. Wanneer je Azure Functions draait in Node.js 14 of hoger, kun je ervoor kiezen je functies te schrijven met behulp van de syntax van ES-modules.

Als u ES-modules in een functie wilt gebruiken, wijzigt u de bestandsnaam in een .mjs extensie. Het volgende index.mjs-bestand is een door HTTP geactiveerde functie die gebruikmaakt van de syntaxis van ES-modules om de uuid bibliotheek te importeren en een waarde te retourneren.

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,
});

Functieinvoerpunt configureren

Gebruik de function.json eigenschappen scriptFile en entryPoint om de locatie en naam van je geëxporteerde functie in te stellen. Wanneer je TypeScript gebruikt, heb je de scriptFile eigenschap nodig en die zou moeten wijzen op de gecompileerde JavaScript.

Het gebruiken van scriptFile

Standaard draait een JavaScript-functie vanaf index.js. Dit bestand deelt dezelfde oudermap als het bijbehorende function.json bestand.

Gebruik scriptFile om je mapstructuur te organiseren. Het volgende voorbeeld laat een manier zien om je mappen in te stellen:

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

Het function.json bestand voor myFirstFunction moet een scriptFile eigenschap bevatten die verwijst naar het bestand met de geëxporteerde functie om uit te voeren.

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

Het gebruiken van entryPoint

In het v3-model moet je een functie exporteren door te gebruiken module.exports zodat de functie gevonden en uitgevoerd kan worden. Standaard is de functie die wordt uitgevoerd wanneer deze wordt geactiveerd de enige export uit dat bestand. Het kan ook de exportnaam run of de exportnaam indexzijn. In het volgende voorbeeld wordt entryPoint in function.json ingesteld op een aangepaste waarde: "logHello".

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

module.exports = { logHello };

Aanbevelingen

Deze sectie beschrijft verschillende impactvolle patronen voor Node.js apps die je zou moeten volgen.

App Service-abonnementen met één vCPU kiezen

Wanneer je een functie-app maakt die het App Service-plan gebruikt, kies dan een enkel vCPU-plan in plaats van een plan met meerdere vCPU's. Tegenwoordig draait Functions Node.js functies efficiënter op single-vCPU VM's, en het gebruik van grotere VM's levert niet de verwachte prestatieverbeteringen op. Wanneer nodig kun je opschalen door meer single-vCPU VM-instanties toe te voegen, of je kunt autoscale inschakelen. Zie Het aantal exemplaren handmatig of automatisch schalen voor meer informatie.

Uitvoeren vanuit een pakketbestand

Wanneer u Azure Functions ontwikkelt in het serverloze hostingmodel, is koude start een realiteit. Koude start verwijst naar de eerste keer dat uw functie-app wordt gestart na een periode van inactiviteit, wat langer duurt om te starten. Voor Node.js apps met grote afhankelijkheidsstructuren in het bijzonder kan koude start aanzienlijk zijn. Als u het koude startproces wilt versnellen, voert u uw functies zo mogelijk uit als een pakketbestand . Veel implementatiemethoden gebruiken dit model standaard, maar als je last hebt van grote cold starts, controleer dan of je op deze manier draait.

Gebruiken async en await

Wanneer je Azure Functions in Node.jsschrijft, schrijf code met behulp van de async en await sleutelwoorden. Code schrijven met async en await in plaats van callbacks of .then met en .catch met beloftes helpt je twee veelvoorkomende problemen te vermijden:

  • Het genereren van onopgevangen uitzonderingen die het Node.js proces laten crashen, dat mogelijk de uitvoering van andere functies beïnvloedt.
  • Onverwacht gedrag, zoals ontbrekende logregels van context.log, veroorzaakt door asynchrone aanroepen die niet goed worden gewacht.

In het volgende voorbeeld wordt de asynchrone methode fs.readFile aangeroepen met een error-first callback-functie als de tweede parameter. Deze code veroorzaakt beide problemen die eerder zijn genoemd. Een uitzondering die niet expliciet in het juiste bereik wordt opgevangen, kan het hele proces laten crashen (probleem #1). Terugkeren zonder ervoor te zorgen dat de callback wordt afgerond betekent dat de HTTP-respons soms een leeg lichaam heeft (probleem #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 };
    },
});

In het volgende voorbeeld wordt de asynchrone methode fs.readFile aangeroepen met een error-first callback-functie als de tweede parameter. Deze code veroorzaakt beide eerder genoemde problemen. Een uitzondering die niet expliciet in de juiste scope wordt vastgelegd, kan het hele proces laten crashen (probleem #1). Het aanroepen van de verouderde context.done() methode buiten het bereik van de callback kan aangeven dat de functie is voltooid voordat het bestand wordt gelezen (probleem #2). In dit voorbeeld resulteert het aanroepen context.done() van te vroeg in ontbrekende logboekvermeldingen die beginnen met 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();
};

Gebruik de zoekwoorden async en await om beide problemen te voorkomen. De meeste API's in het Node.js-ecosysteem ondersteunen nu beloften in een of andere vorm. Bijvoorbeeld, vanaf versie 14 biedt Node.js een fs/promises API ter vervanging van de fs callback-API.

In het volgende voorbeeld mislukken eventuele niet-verwerkte uitzonderingen die worden gegenereerd tijdens de uitvoering van de functie alleen de afzonderlijke aanroep die de uitzondering heeft gegenereerd. Het await trefwoord betekent dat de volgende stappen readFile alleen worden uitgevoerd nadat het is voltooid.

// 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;
        }
    },
});

Wanneer je async en await gebruikt, hoef je de callback van context.done() niet aan te roepen.

// 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}`);
};

Problemen oplossen

Raadpleeg de handleiding voor het oplossen van problemen met Node.js.

Volgende stappen

Voor meer informatie raadpleegt u de volgende bronnen: