Delen via


Ontwikkelaarshandleiding voor Azure Functions Node.js

Deze handleiding is een inleiding tot het ontwikkelen van Azure Functions met behulp van JavaScript of TypeScript. In het artikel wordt ervan uitgegaan dat u de ontwikkelaarshandleiding van Azure Functions al hebt gelezen.

Belangrijk

De inhoud van dit artikel wordt gewijzigd op basis van uw keuze uit het Node.js programmeermodel in de selector boven aan deze pagina. De versie die u kiest, moet overeenkomen met de versie van het @azure/functions npm-pakket dat u in uw app gebruikt. Als u dat pakket niet in uw package.jsonlijst hebt, is de standaardwaarde v3. Meer informatie over de verschillen tussen v3 en v4 in de migratiehandleiding.

Als Node.js ontwikkelaar bent u mogelijk ook geïnteresseerd in een van de volgende artikelen:

Aan de slag Concepten Gestuurd leren

Overwegingen

  • Het Node.js programmeermodel mag niet worden verward met de Azure Functions-runtime:
    • Programmeermodel: Definieert hoe u uw code ontwerpt en specifiek is voor JavaScript en TypeScript.
    • Runtime: Definieert het onderliggende gedrag van Azure Functions en wordt gedeeld in alle talen.
  • De versie van het programmeermodel is strikt gekoppeld aan de versie van het @azure/functions npm-pakket. Deze versie wordt onafhankelijk van de runtime geversied. Zowel de runtime als het programmeermodel gebruiken het nummer 4 als de nieuwste primaire versie, maar dat is toeval.
  • U kunt de v3- en v4-programmeermodellen niet combineren in dezelfde functie-app. Zodra u één v4-functie in uw app registreert, worden alle v3-functies die zijn geregistreerd in function.json bestanden genegeerd.

Ondersteunde versies

In de volgende tabel ziet u elke versie van het Node.js programmeermodel, samen met de ondersteunde versies van de Azure Functions-runtime en Node.js.

Versie van programmeermodel Ondersteuningsniveau Runtimeversie van Functions Node.js versie Beschrijving
4.x GA 4.25+ 20.x, 18.x Ondersteunt een flexibele bestandsstructuur en codegerichte benadering voor triggers en bindingen.
3.x GA 4.x 20.x, 18.x, 16.x, 14.x Vereist een specifieke bestandsstructuur met uw triggers en bindingen die zijn gedeclareerd in een 'function.json'-bestand
2.x n.v.t. 3.x 14.x, 12.x, 10.x Bereikt einde van de ondersteuning op 13 december 2022. Zie Functions-versies voor meer informatie.
1.x n.v.t. 2.x 10.x, 8.x Bereikt einde van de ondersteuning op 13 december 2022. Zie Functions-versies voor meer informatie.

Mapstructuur

De vereiste mapstructuur voor een JavaScript-project ziet eruit als 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-instellingen 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 scriptFile als u dit standaardbestandspad wilt wijzigen.
  • .funcignore: (Optioneel) Declareert bestanden die niet naar Azure mogen worden gepubliceerd. Meestal bevat dit bestand .vscode/ om uw editorinstelling te negeren, test/ testcases te negeren en local.settings.json om te voorkomen dat lokale app-instellingen worden gepubliceerd.
  • host.json: bevat configuratieopties die van invloed zijn op alle functies in een exemplaar van een functie-app. Dit bestand wordt wel gepubliceerd naar Azure. Niet alle opties worden ondersteund bij lokaal uitvoeren. Zie host.json voor meer informatie.
  • local.settings.json: wordt gebruikt voor het opslaan van app-instellingen en verbindingsreeks s wanneer deze lokaal wordt uitgevoerd. Dit bestand wordt niet gepubliceerd naar Azure. Zie local.settings.file voor meer informatie.
  • package.json: bevat configuratieopties zoals een lijst met pakketafhankelijkheden, het hoofdinvoerpunt en scripts.

De aanbevolen mapstructuur voor een JavaScript-project ziet er als volgt uit:

<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-instellingen 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 naar Azure mogen worden gepubliceerd. Meestal bevat dit bestand .vscode/ om uw editorinstelling te negeren, test/ testcases te negeren en local.settings.json om te voorkomen dat lokale app-instellingen worden gepubliceerd.
  • host.json: bevat configuratieopties die van invloed zijn op alle functies in een exemplaar van een functie-app. Dit bestand wordt wel gepubliceerd naar Azure. Niet alle opties worden ondersteund bij lokaal uitvoeren. Zie host.json voor meer informatie.
  • local.settings.json: wordt gebruikt voor het opslaan van app-instellingen en verbindingsreeks s wanneer deze lokaal wordt uitgevoerd. Dit bestand wordt niet gepubliceerd naar Azure. Zie local.settings.file voor meer informatie.
  • package.json: bevat configuratieopties zoals een lijst met pakketafhankelijkheden, het hoofdinvoerpunt en scripts.

Een functie registreren

Het v3-model registreert een functie op basis van het bestaan van twee bestanden. Eerst hebt u een function.json bestand in een map nodig die zich één niveau lager bevindt dan de hoofdmap van uw app. Ten tweede hebt u een JavaScript-bestand nodig dat uw functie exporteert . Standaard zoekt het model naar een index.js bestand in dezelfde map als uw function.json. Als u TypeScript gebruikt, moet u de scriptFile eigenschap gebruiken function.json om naar het gecompileerde JavaScript-bestand te verwijzen. Als u de bestandslocatie of exportnaam van uw functie wilt aanpassen, raadpleegt u het configureren van het toegangspunt van uw functie.

De functie die u exporteert, moet altijd worden gedeclareerd als een async function in het v3-model. U kunt een synchrone functie exporteren, maar vervolgens moet u aanroepen context.done() om aan te geven dat uw functie is voltooid, wat is afgeschaft en niet wordt aanbevolen.

Uw functie wordt doorgegeven context als het eerste argument en uw invoer als de resterende argumenten.

Het volgende voorbeeld is een eenvoudige functie waarmee wordt geregistreerd dat deze is geactiveerd en reageert met Hello, world!:

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "authLevel": "anonymous",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}
module.exports = async function (context, request) {
    context.log('Http function was triggered.');
    context.res = { body: 'Hello, world!' };
};

Het programmeermodel laadt uw functies op basis van het main veld in uw package.json. U kunt het main veld instellen op één bestand of meerdere bestanden met behulp van een glob-patroon. In de volgende tabel ziet u voorbeeldwaarden voor het main veld:

Opmerking Beschrijving
src/index.js Registreer functies uit één hoofdbestand.
src/functions/*.js Registreer elke functie uit een eigen bestand.
src/{index.js,functions/*.js} Een combinatie waarbij u elke functie registreert vanuit een eigen bestand, maar u hebt nog steeds een hoofdbestand voor algemene code op app-niveau.

Als u een functie wilt registreren, moet u het app object importeren uit de @azure/functions npm-module en de methode aanroepen die specifiek is voor uw triggertype. Het eerste argument bij het registreren van een functie is de functienaam. Het tweede argument is een options object dat de configuratie voor uw trigger, uw handler en andere invoer of uitvoer aangeeft. In sommige gevallen waarin triggerconfiguratie niet nodig is, kunt u de handler rechtstreeks doorgeven als het tweede argument in plaats van een options object.

Het registreren van een functie kan worden uitgevoerd vanuit elk bestand in uw project, zolang dat bestand (direct of indirect) wordt geladen op basis van het main veld in uw package.json bestand. De functie moet worden geregistreerd in een globaal bereik, omdat u functies niet kunt registreren zodra de uitvoeringen zijn gestart.

Het volgende voorbeeld is een eenvoudige functie waarmee wordt geregistreerd dat deze is geactiveerd en reageert met Hello, world!:

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

app.http('helloWorld1', {
    methods: ['POST', 'GET'],
    handler: async (request, context) => {
        context.log('Http function was triggered.');
        return { body: 'Hello, world!' };
    }
});

Invoer en uitvoer

Uw functie is vereist om precies één primaire invoer met de naam van de trigger te hebben. Het kan ook secundaire invoer en/of uitvoer hebben. Invoer en uitvoer worden geconfigureerd in uw function.json bestanden en worden ook wel bindingen genoemd.

Invoerwaarden

Invoer zijn bindingen die direction zijn ingesteld op in. Het belangrijkste verschil tussen een trigger en een secundaire invoer is dat het type voor een trigger eindigt, Triggerbijvoorbeeld type blobTrigger versus type blob. De meeste functies gebruiken alleen een trigger en er worden niet veel secundaire invoertypen ondersteund.

Invoer kan op verschillende manieren worden geopend:

  • [Aanbevolen] Als argumenten die worden doorgegeven aan uw functie: gebruik de argumenten in dezelfde volgorde waarin ze zijn gedefinieerd function.json. De name eigenschap die is gedefinieerd, function.json hoeft niet overeen te komen met de naam van uw argument, hoewel dit wordt aanbevolen in het belang van de organisatie.

    module.exports = async function (context, myTrigger, myInput, myOtherInput) { ... };
    
  • Als eigenschappen van context.bindings: Gebruik de sleutel die overeenkomt met de name eigenschap die is gedefinieerd in function.json.

    module.exports = async function (context) {
        context.log("This is myTrigger: " + context.bindings.myTrigger);
        context.log("This is myInput: " + context.bindings.myInput);
        context.log("This is myOtherInput: " + context.bindings.myOtherInput);
    };
    

Uitvoerwaarden

Uitvoer zijn bindingen die direction zijn ingesteld op out en kunnen op verschillende manieren worden ingesteld:

  • [Aanbevolen voor één uitvoer] Retourneer de waarde rechtstreeks: Als u een asynchrone functie gebruikt, kunt u de waarde rechtstreeks retourneren. U moet de name eigenschap van de uitvoerbinding $return wijzigen in zoals in function.json het volgende voorbeeld:

    {
        "name": "$return",
        "type": "http",
        "direction": "out"
    }
    
    module.exports = async function (context, request) {
        return {
            body: "Hello, world!"
        };
    }
    
  • [Aanbevolen voor meerdere uitvoerbewerkingen] Retourneert een object met alle uitvoerwaarden: als u een asynchrone functie gebruikt, kunt u een object retourneren met een eigenschap die overeenkomt met de naam van elke binding in uw function.json. In het volgende voorbeeld worden uitvoerbindingen met de naam httpResponse en queueOutput gebruikt:

    {
        "name": "httpResponse",
        "type": "http",
        "direction": "out"
    },
    {
        "name": "queueOutput",
        "type": "queue",
        "direction": "out",
        "queueName": "helloworldqueue",
        "connection": "storage_APPSETTING"
    }
    
    module.exports = async function (context, request) {
        let message = 'Hello, world!';
        return {
            httpResponse: {
                body: message
            },
            queueOutput: message
        };
    };
    
  • Stel waarden in op context.bindings: Als u geen asynchrone functie gebruikt of u de vorige opties niet wilt gebruiken, kunt u waarden rechtstreeks context.bindingsinstellen, waarbij de sleutel overeenkomt met de naam van de binding. In het volgende voorbeeld worden uitvoerbindingen met de naam httpResponse en queueOutput gebruikt:

    {
        "name": "httpResponse",
        "type": "http",
        "direction": "out"
    },
    {
        "name": "queueOutput",
        "type": "queue",
        "direction": "out",
        "queueName": "helloworldqueue",
        "connection": "storage_APPSETTING"
    }
    
    module.exports = async function (context, request) {
        let message = 'Hello, world!';
        context.bindings.httpResponse = {
            body: message
        };
        context.bindings.queueOutput = message;
    };
    

Gegevenstype Bindingen

U kunt de dataType eigenschap op een invoerbinding gebruiken om het type invoer te wijzigen, maar er gelden enkele beperkingen:

  • Alleen in Node.js string en binary worden ondersteund (stream niet)
  • Voor HTTP-invoer wordt de dataType eigenschap genegeerd. Gebruik in plaats daarvan eigenschappen voor het request object om de hoofdtekst in de gewenste indeling op te halen. Zie HTTP-aanvraag voor meer informatie.

In het volgende voorbeeld van een trigger voor een opslagwachtrij is het standaardtype myQueueItem een string, maar als u dit instelt dataType binary, wordt het type gewijzigd in een Node.jsBuffer.

{
    "name": "myQueueItem",
    "type": "queueTrigger",
    "direction": "in",
    "queueName": "helloworldqueue",
    "connection": "storage_APPSETTING",
    "dataType": "binary"
}
const { Buffer } = require('node:buffer');

module.exports = async function (context, myQueueItem) {
    if (typeof myQueueItem === 'string') {
        context.log('myQueueItem is a string');
    } else if (Buffer.isBuffer(myQueueItem)) {
        context.log('myQueueItem is a buffer');
    }
};

Uw functie is vereist om precies één primaire invoer met de naam van de trigger te hebben. Het kan ook secundaire invoer hebben, een primaire uitvoer genaamd de retouruitvoer en/of secundaire uitvoer. Invoer en uitvoer worden ook wel bindingen genoemd buiten de context van het Node.js programmeermodel. Vóór v4 van het model zijn deze bindingen geconfigureerd in function.json bestanden.

Triggerinvoer

De trigger is de enige vereiste invoer of uitvoer. Voor de meeste triggertypen registreert u een functie met behulp van een methode in het app object met de naam van het triggertype. U kunt configuratie opgeven die specifiek is voor de trigger rechtstreeks op het options argument. Met een HTTP-trigger kunt u bijvoorbeeld een route opgeven. Tijdens de uitvoering wordt de waarde die overeenkomt met deze trigger doorgegeven als het eerste argument aan uw handler.

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

app.http('helloWorld1', {
    route: 'hello/world',
    handler: async (request, context) => {
        ...
    }
});

Uitvoer retourneren

De retouruitvoer is optioneel en in sommige gevallen standaard geconfigureerd. Een HTTP-trigger die is geregistreerd app.http , is bijvoorbeeld geconfigureerd om automatisch een HTTP-antwoorduitvoer te retourneren. Voor de meeste uitvoertypen geeft u de retourconfiguratie voor het options argument op met behulp van het output object dat uit de @azure/functions module is geëxporteerd. Tijdens de uitvoering stelt u deze uitvoer in door deze vanuit uw handler te retourneren.

In het volgende voorbeeld wordt een timertrigger en uitvoer van een opslagwachtrij gebruikt:

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

app.timer('timerTrigger1', {
    schedule: '0 */5 * * * *',
    return: output.storageQueue({
        connection: 'storage_APPSETTING',
        ...
    }),
    handler: (myTimer, context) => {
        return { hello: 'world' }
    }
});

Extra invoer en uitvoer

Naast de trigger en retour kunt u extra invoer of uitvoer opgeven voor het argument bij het options registreren van een functie. De input en output objecten die uit de @azure/functions module worden geëxporteerd, bieden typespecifieke methoden om de configuratie samen te stellen. Tijdens de uitvoering krijgt of stelt u de waarden in met context.extraInputs.get of context.extraOutputs.setstelt u het oorspronkelijke configuratieobject door als het eerste argument.

Het volgende voorbeeld is een functie die wordt geactiveerd door een opslagwachtrij, met een extra opslagblobinvoer die wordt gekopieerd naar een extra opslagblobuitvoer. Het wachtrijbericht moet de naam van een bestand zijn en vervangt {queueTrigger} als de blobnaam die moet worden gekopieerd, met behulp van een bindingexpressie.

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

const blobInput = input.storageBlob({
    connection: 'storage_APPSETTING',
    path: 'helloworld/{queueTrigger}',
});

const blobOutput = output.storageBlob({
    connection: 'storage_APPSETTING',
    path: 'helloworld/{queueTrigger}-copy',
});

app.storageQueue('copyBlob1', {
    queueName: 'copyblobqueue',
    connection: 'storage_APPSETTING',
    extraInputs: [blobInput],
    extraOutputs: [blobOutput],
    handler: (queueItem, context) => {
        const blobInputValue = context.extraInputs.get(blobInput);
        context.extraOutputs.set(blobOutput, blobInputValue);
    }
});

Algemene invoer en uitvoer

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

Aanroepcontext

Elke aanroep van uw functie wordt doorgegeven aan een aanroepobject context , gebruikt voor het lezen van invoer, het instellen van uitvoer, schrijven naar logboeken en het lezen van verschillende metagegevens. In het v3-model is het contextobject altijd het eerste argument dat aan uw handler wordt doorgegeven.

Het context object heeft de volgende eigenschappen:

Eigenschappen Beschrijving
invocationId De id van de huidige functie-aanroep.
executionContext Bekijk de uitvoeringscontext.
bindings Zie bindingen.
bindingData Metagegevens over de triggerinvoer voor deze aanroep, niet inclusief 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:

Eigenschappen Beschrijving
invocationId De id van de huidige functie-aanroep.
functionName De naam van de functie die wordt aangeroepen. 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 context voor opnieuw proberen.

context.executionContext.retryContext

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

Eigenschappen 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 middelen om het voor onbepaalde tijd opnieuw te proberen.
exception Uitzondering die de nieuwe poging heeft veroorzaakt.

context.bindingen

Het context.bindings object wordt gebruikt om invoer te lezen of uitvoer in te stellen. Het volgende voorbeeld is een opslagwachtrijtrigger die gebruikt context.bindings om een opslagblobinvoer te kopiëren naar een uitvoer van een opslagblob. De inhoud van het wachtrijbericht wordt vervangen {queueTrigger} als de bestandsnaam die moet worden gekopieerd, 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.done

De context.done methode is afgeschaft. Voordat asynchrone functies werden ondersteund, zou u aangeven dat uw functie wordt uitgevoerd door het aanroepen context.done()van:

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

Het is nu raadzaam om de aanroep te verwijderen en uw functie als asynchroon te context.done() markeren, zodat deze een belofte retourneert (zelfs als u niets await doet). Zodra uw functie is voltooid (met andere woorden, de geretourneerde belofte wordt omgezet), weet het v3-model dat uw functie is voltooid.

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

Elke aanroep van uw functie wordt doorgegeven aan een aanroepobject context , met informatie over uw aanroep en methoden die worden gebruikt voor logboekregistratie. In het v4-model is het context object doorgaans het tweede argument dat wordt doorgegeven aan uw handler.

De InvocationContext klasse heeft de volgende eigenschappen:

Eigenschappen Beschrijving
invocationId De id van de huidige functie-aanroep.
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 context voor opnieuw proberen.
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 met standaardinstellingen expliciet zijn opgegeven.

Context voor opnieuw proberen

Het retryContext object heeft de volgende eigenschappen:

Eigenschappen 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 middelen 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 is het raadzaam om context.log() logboeken te schrijven. Azure Functions kan worden geïntegreerd 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 Azure Functions bewaken voor meer informatie.

Notitie

Als u de alternatieve methode Node.js console.log gebruikt, worden deze logboeken bijgehouden op app-niveau en worden deze niet gekoppeld aan een specifieke functie. Het wordt ten zeerste aanbevolen om logboekregistratie te gebruiken context in plaats van console dat alle logboeken zijn gekoppeld aan een specifieke functie.

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 zijn de volgende methoden beschikbaar waarmee u logboeken op specifieke niveaus kunt schrijven:

Wijze Description
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 Description
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

Met Azure Functions kunt u het drempelwaardeniveau definiëren dat moet worden gebruikt bij het bijhouden en weergeven van logboeken. Als u de drempelwaarde wilt instellen, gebruikt u de logging.logLevel eigenschap in het host.json bestand. Met deze eigenschap kunt u een standaardniveau definiëren dat wordt toegepast op alle functies of een drempelwaarde voor elke afzonderlijke functie. Zie Bewaking configureren voor Azure Functions voor meer informatie.

Aangepaste gegevens bijhouden

Standaard schrijft Azure Functions uitvoer als traceringen naar Application Insights. Voor meer controle kunt u in plaats daarvan de Application Insights Node.js SDK gebruiken om aangepaste gegevens naar uw Application Insights-exemplaar te verzenden.

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 kunt u alle automatisch gegenereerde en aangepaste logboeken correleren voor een bepaalde functie-aanroep.

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

De aanvraag kan op verschillende manieren worden geopend:

  • 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}"`);
    
  • Vanaf de benoemde invoerbindingen: deze optie werkt hetzelfde als elke niet-HTTP-binding. De bindingsnaam moet function.json 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 Type Description
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. Het wordt aanbevolen om in plaats daarvan te gebruiken request.getHeader('header-name') , wat niet hoofdlettergevoelig is.
query Record<string, string> Queryreeksparametersleutels en -waarden uit de URL.
params Record<string, string> Routeparametersleutels 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. body Anders is dit een tekenreeks.
rawBody string De hoofdtekst als een tekenreeks. Ondanks de naam retourneert deze eigenschap geen buffer.
bufferBody Buffer Het lichaam als buffer.

De aanvraag kan worden geopend als het eerste argument voor uw 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 Type Description
method string Http-aanvraagmethode die wordt gebruikt om deze functie aan te roepen.
url string Aanvraag-URL.
headers Headers HTTP-aanvraagheaders.
query URLSearchParams Queryreeksparametersleutels en -waarden uit de URL.
params Record<string, string> Routeparametersleutels 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 Hoofdtekst als leesbare stroom.
bodyUsed boolean Een Booleaanse waarde die aangeeft of de hoofdtekst al is gelezen.

Om toegang te krijgen tot de hoofdtekst van een aanvraag of antwoord, kunnen de volgende methoden worden gebruikt:

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

Notitie

De hoofdtekstfuncties kunnen slechts eenmaal worden uitgevoerd; volgende aanroepen worden omgezet met lege tekenreeksen/ArrayBuffers.

HTTP-antwoord

Het antwoord kan op verschillende manieren worden ingesteld:

  • 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 context.done() aan en kan niet worden gebruikt 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 Type Description
headers Record<string, string> (optioneel) HTTP-antwoordheaders.
cookies Cookie[] (optioneel) HTTP-antwoordcookies.
body any (optioneel) Hoofdtekst http-antwoord.
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 deze 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 Description
status() Hiermee stelt u de status in.
setHeader() Hiermee stelt u een koptekstveld in. OPMERKING: res.set() en res.header() worden ook ondersteund en doen hetzelfde.
getHeader() Een koptekstveld ophalen. OPMERKING: res.get() wordt ook ondersteund en doet hetzelfde.
removeHeader() Hiermee verwijdert u een koptekst.
type() Hiermee stelt u de header 'inhoudstype' in.
send() Deze methode is afgeschaft. Hiermee stelt u de hoofdtekst en aanroepen context.done() in 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.

Het antwoord kan op verschillende manieren worden ingesteld:

  • Als eenvoudige interface met type HttpResponseInit: Deze optie is de meest beknopte manier om antwoorden te retourneren.

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

    De HttpResponseInit interface heeft de volgende eigenschappen:

    Eigenschap Type Description
    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 Type Description
    status number HTTP-antwoordstatuscode.
    headers Headers HTTP-antwoordheaders.
    cookies Cookie[] HTTP-antwoordcookies.
    body ReadableStream | null Hoofdtekst als leesbare stroom.
    bodyUsed boolean Een Booleaanse waarde die aangeeft of de hoofdtekst al is gelezen.

HTTP-streams

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 FUNCTIONS_REQUEST_BODY_SIZE_LIMIT instelling in Azure. De standaard toegestane maximale grootte van de hoofdtekst is 104857600, waardoor uw aanvragen worden beperkt tot een grootte van ~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

In dit voorbeeld ziet u een door HTTP geactiveerde functie die gegevens ontvangt via een HTTP POST-aanvraag en de functie deze gegevens naar een opgegeven uitvoerbestand streamt:

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

In dit voorbeeld ziet u een door HTTP geactiveerde functie die de inhoud van een bestand streamt als reactie op binnenkomende HTTP GET-aanvragen:

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

Bekijk dit voorbeeld op GitHub voor een kant-en-klare voorbeeld-app met behulp van streams.

Overwegingen voor stromen

  • Gebruik request.body dit om het maximale voordeel te krijgen van het gebruik van streams. U kunt nog steeds methoden blijven gebruiken, zoals request.text(), die altijd de hoofdtekst retourneren als een tekenreeks.

Hooks

Hooks worden niet ondersteund in het v3-model. 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. Hooks worden uitgevoerd in de volgorde waarin ze zijn geregistreerd en kunnen worden geregistreerd vanuit elk bestand in uw app. Er zijn momenteel twee bereiken van hooks, het niveau 'app' en 'aanroep'.

Aanroephaken

Aanroephaken worden eenmaal uitgevoerd per aanroep van uw functie, voor in een preInvocation haak of na in een postInvocation haak. Standaard wordt uw hook uitgevoerd voor alle triggertypen, maar u 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');

app.hook.preInvocation((context) => {
    if (context.invocationContext.options.trigger.type === 'httpTrigger') {
        context.invocationContext.log(
            `preInvocation hook executed for http function ${context.invocationContext.functionName}`
        );
    }
});

app.hook.postInvocation((context) => {
    if (context.invocationContext.options.trigger.type === 'httpTrigger') {
        context.invocationContext.log(
            `postInvocation hook executed for http function ${context.invocationContext.functionName}`
        );
    }
});

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

Het PreInvocationContext object heeft de volgende eigenschappen:

Eigenschappen Beschrijving
inputs De argumenten die zijn doorgegeven aan de aanroep.
functionHandler De functie-handler voor de aanroep. Wijzigingen in deze waarde zijn van invloed op de functie zelf.
invocationContext Het aanroepcontextobject dat is doorgegeven aan de functie.
hookData De aanbevolen plaats voor het opslaan en delen van gegevens tussen hooks in hetzelfde bereik. U moet een unieke eigenschapsnaam gebruiken, zodat deze niet conflicteert met de gegevens van andere hooks.

Het PostInvocationContext object heeft de volgende eigenschappen:

Eigenschappen Beschrijving
inputs De argumenten die zijn doorgegeven 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 gegenereerd, of null/undefined als er geen fout is. Wijzigingen in deze waarde zijn van invloed op het algehele resultaat van de functie.
invocationContext Het aanroepcontextobject dat is doorgegeven aan de functie.
hookData De aanbevolen plaats voor het opslaan en delen van gegevens tussen hooks in hetzelfde bereik. U moet een unieke eigenschapsnaam gebruiken, zodat deze niet conflicteert met de gegevens van andere hooks.

App-hooks

App-hooks worden eenmaal per exemplaar van uw app uitgevoerd, hetzij tijdens het opstarten in een appStart hook of tijdens beëindiging in een appTerminate hook. App-beëindigde hooks hebben een beperkte tijd om uit te voeren en worden niet uitgevoerd in alle scenario's.

De Azure Functions-runtime biedt momenteel geen ondersteuning voor contextlogboekregistratie 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');

app.hook.appStart((context) => {
    // add your logic here
});

app.hook.appTerminate((context) => {
    // add your logic here
});

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

Het AppStartContext object heeft de volgende eigenschappen:

Eigenschappen Beschrijving
hookData De aanbevolen plaats voor het opslaan en delen van gegevens tussen hooks in hetzelfde bereik. U moet een unieke eigenschapsnaam gebruiken, zodat deze niet conflicteert met de gegevens van andere hooks.

Het AppTerminateContext object heeft de volgende eigenschappen:

Eigenschappen Beschrijving
hookData De aanbevolen plaats voor het opslaan en delen van gegevens tussen hooks in hetzelfde bereik. U moet een unieke eigenschapsnaam gebruiken, zodat deze niet conflicteert met de gegevens van andere hooks.

Schalen en gelijktijdigheid

Azure Functions bewaakt standaard automatisch de belasting van uw toepassing en maakt zo nodig meer hostexemplaren voor Node.js. Azure Functions maakt gebruik van ingebouwde drempelwaarden (niet door de gebruiker configureerbaar) voor verschillende triggertypen om te bepalen wanneer exemplaren moeten 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. Vervolgens probeert Azure Functions gelijktijdige functieaanroepen gelijkmatig over deze werkrollen 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 te voldoen aan de vraag.

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 u deze instelling gebruikt, wordt het ten zeerste aanbevolen om deze nadelen te compenseren door uit te voeren vanuit een pakketbestand.

Node-versie

U kunt de huidige versie zien die door de runtime wordt gebruikt door logboekregistratie uit elke functie uit te voeren process.version . 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 u windows gebruikt, wordt de Node.js versie ingesteld door de WEBSITE_NODE_DEFAULT_VERSION toepassingsinstelling. Deze instelling kan worden bijgewerkt met behulp van de Azure CLI of in Azure Portal.

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. Als u uw runtime-versie wilt upgraden, raadpleegt u Migrate-apps van Azure Functions versie 3.x naar versie 4.x.

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

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

Hiermee stelt u de toepassingsinstelling voor WEBSITE_NODE_DEFAULT_VERSION de ondersteunde LTS-versie van ~20.

Nadat de wijzigingen zijn aangebracht, wordt de functie-app opnieuw opgestart. Zie het ondersteuningsbeleid voor Language Runtime voor meer informatie over de ondersteuning van Functions voor Node.js.

Omgevingsvariabelen

Omgevingsvariabelen kunnen handig zijn voor operationele geheimen (verbindingsreeks s, sleutels, eindpunten, enzovoort) of omgevingsinstellingen zoals profileringsvariabelen. U kunt omgevingsvariabelen toevoegen in zowel uw lokale als cloudomgevingen en deze openen via process.env uw 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 toepassingsinstellingen, zoals service-verbindingsreeks s, instellen en gebruiken en deze instellingen beschikbaar maken 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 werkrollen

Er zijn verschillende omgevingsvariabelen voor Functions die specifiek zijn voor Node.js:

languageWorkers__node__arguments

Met deze instelling kunt u aangepaste argumenten opgeven bij het starten van uw Node.js proces. Het wordt meestal lokaal gebruikt om de werkrol te starten in de foutopsporingsmodus, maar kan ook worden gebruikt in Azure als u aangepaste argumenten nodig hebt.

Waarschuwing

Vermijd indien mogelijk het gebruik languageWorkers__node__arguments in Azure omdat dit een negatief effect kan hebben op koude begintijden. In plaats van vooraf verwarmde werkrollen te gebruiken, moet de runtime een nieuwe werkrol helemaal opnieuw starten met uw aangepaste argumenten.

logging__logLevel__Worker

Met deze instelling wordt het standaardlogboekniveau voor Node.js specifieke werklogboeken aangepast. Standaard worden alleen waarschuwings- of foutlogboeken weergegeven, maar u kunt deze information instellen op of debug om problemen met de Node.js worker vast te stellen. Zie Logboekniveaus configureren voor meer informatie.

ECMAScript-modules (preview)

Notitie

Aangezien ECMAScript-modules momenteel een preview-functie zijn 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 u Azure Functions uitvoert in Node.js 14 of hoger, kunt u ervoor kiezen om uw functies te schrijven met behulp van de syntaxis 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

De function.json eigenschappen scriptFile en entryPoint kunnen worden gebruikt om de locatie en naam van uw geëxporteerde functie te configureren. De scriptFile eigenschap is vereist wanneer u TypeScript gebruikt en moet verwijzen naar het gecompileerde JavaScript.

scriptFile gebruiken

Standaard wordt een JavaScript-functie uitgevoerd vanuit index.js, een bestand dat dezelfde bovenliggende map deelt als de bijbehorende function.jsonmap.

scriptFile kan worden gebruikt om een mapstructuur op te halen die eruitziet als in het volgende voorbeeld:

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

De function.json for myFirstFunction moet een scriptFile eigenschap bevatten die verwijst naar het bestand met de geëxporteerde functie die moet worden uitgevoerd.

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

entryPoint gebruiken

In het v3-model moet een functie worden geëxporteerd om module.exports te kunnen worden gevonden en uitgevoerd. Standaard is de functie die wordt uitgevoerd wanneer deze wordt geactiveerd, de enige export uit dat bestand, de export met de naam runof de export met de naam index. In het volgende voorbeeld wordt entryPoint function.json een aangepaste waarde ingesteld: 'logHello':

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

module.exports = { logHello };

Lokale foutopsporing

Het is raadzaam VS Code te gebruiken voor lokale foutopsporing, waardoor uw Node.js proces automatisch wordt gestart in de foutopsporingsmodus en wordt gekoppeld aan het proces voor u. Zie De functie lokaal uitvoeren voor meer informatie.

Als u een ander hulpprogramma gebruikt voor foutopsporing of als u het Node.js proces handmatig wilt starten in de foutopsporingsmodus, voegt "languageWorkers__node__arguments": "--inspect" u deze toe aan Values uw local.settings.json. Het --inspect argument geeft aan Node.js standaard te luisteren naar een foutopsporingsclient op poort 9229. Zie de handleiding voor Node.js foutopsporing voor meer informatie.

Aanbevelingen

In deze sectie worden verschillende impactvolle patronen beschreven voor Node.js apps die u wordt aangeraden te volgen.

App Service-abonnementen met één vCPU kiezen

Wanneer u een functie-app maakt die gebruikmaakt van het App Service-plan, raden we u aan een abonnement met één vCPU te selecteren in plaats van een plan met meerdere vCPU's. Tegenwoordig worden Node.js functies efficiënter uitgevoerd op VM's met één vCPU en levert het gebruik van grotere VM's niet de verwachte prestatieverbeteringen op. Indien nodig kunt u handmatig uitschalen door meer VM-exemplaren met één vCPU toe te voegen of door automatische schaalaanpassing in te schakelen. 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 u te maken hebt met grote koude start, moet u controleren of u op deze manier werkt.

Eén statische client gebruiken

Wanneer u een servicespecifieke client in een Azure Functions-toepassing gebruikt, maakt u geen nieuwe client met elke functieaanroep omdat u verbindingslimieten kunt bereiken. Maak in plaats daarvan één statische client in het globale bereik. Zie verbindingen beheren in Azure Functions voor meer informatie.

Gebruiken async en await

Wanneer u Azure Functions in Node.js schrijft, moet u code schrijven met behulp van de async en await trefwoorden. Het schrijven van code met behulp van async en await in plaats van callbacks of .then met .catch Promise helpt bij het voorkomen van twee veelvoorkomende problemen:

  • Het genereren van onopgevallen uitzonderingen die het Node.js proces vastlopen, wat mogelijk van invloed is op de uitvoering van andere functies.
  • Onverwacht gedrag, zoals ontbrekende logboeken, context.logveroorzaakt 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 (probleem 1) vastlopen. Retourneren zonder ervoor te zorgen dat de callback is voltooid, betekent dat het HTTP-antwoord soms een lege hoofdtekst 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 problemen die eerder zijn genoemd. Een uitzondering die niet expliciet in het juiste bereik wordt opgevangen, kan het hele proces (probleem 1) vastlopen. Het aanroepen van de afgeschafte 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 async en await trefwoorden om beide problemen te voorkomen. De meeste API's in het Node.js ecosysteem zijn geconverteerd naar ondersteuningsbeloften in een bepaalde vorm. Vanaf v14 biedt Node.js bijvoorbeeld een fs/promises API om de fs callback-API te vervangen.

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

Met async en await, u hoeft ook niet de context.done() callback 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: