JavaScript-utvecklarhandbok för Azure Functions

Den här guiden innehåller detaljerad information som hjälper dig att utveckla Azure Functions med Hjälp av JavaScript.

Som Express.js, Node.js eller JavaScript-utvecklare bör du överväga att först läsa någon av följande artiklar om du är nybörjare på Azure Functions:

Komma igång Begrepp Interaktiv utbildning

Grundläggande om JavaScript-funktioner

En JavaScript-funktion (Node.js) är en exporterad function funktion som körs när den utlöses (utlösare konfigureras i function.json). Det första argumentet som skickas till varje funktion är ett context objekt som används för att ta emot och skicka bindningsdata, logga och kommunicera med körningen.

Mappstrukturen

Den nödvändiga mappstrukturen för ett JavaScript-projekt ser ut så här. Den här standardinställningen kan ändras. Mer information finns i avsnittet scriptFile nedan.

FunctionsProject
 | - MyFirstFunction
 | | - index.js
 | | - function.json
 | - MySecondFunction
 | | - index.js
 | | - function.json
 | - SharedCode
 | | - myFirstHelperFunction.js
 | | - mySecondHelperFunction.js
 | - node_modules
 | - host.json
 | - package.json
 | - extensions.csproj

I projektets rot finns en delad host.json-fil som kan användas för att konfigurera funktionsappen. Varje funktion har en mapp med en egen kodfil (.js) och en bindningskonfigurationsfil (function.json). Namnet på function.jsonden överordnade katalogen är alltid namnet på din funktion.

Bindningstilläggen som krävs i version 2.x av Functions-körningen definieras i extensions.csproj filen med de faktiska biblioteksfilerna bin i mappen. När du utvecklar lokalt måste du registrera bindningstillägg. När du utvecklar funktioner i Azure Portal görs den här registreringen åt dig.

Exportera en funktion

JavaScript-funktioner måste exporteras via module.exports (eller exports). Din exporterade funktion bör vara en JavaScript-funktion som körs när den utlöses.

Som standard letar Functions-körningen efter funktionen i index.js, där index.js delar samma överordnade katalog som motsvarande function.json. I standardfallet bör den exporterade funktionen vara den enda exporten från filen eller exporten med namnet run eller index. Om du vill konfigurera filplatsen och exportnamnet för funktionen läser du om hur du konfigurerar funktionens startpunkt nedan.

Den exporterade funktionen skickas ett antal argument vid körning. Det första argumentet som krävs är alltid ett context objekt.

När du använder deklarationen async function eller vanliga JavaScript-löften i version 2.x, 3.x eller 4.x av Functions-körningen behöver du inte uttryckligen anropa återanropet context.done för att signalera att funktionen har slutförts. Funktionen slutförs när den exporterade async-funktionen/Promise slutförs.

Följande exempel är en enkel funktion som loggar att den utlöstes och omedelbart slutför körningen.

module.exports = async function (context) {
    context.log('JavaScript trigger function processed a request.');
};

När du exporterar en asynkron funktion kan du också konfigurera en utdatabindning för att ta return värdet. Detta rekommenderas om du bara har en utdatabindning.

Returnerar från funktionen

Om du vill tilldela utdata med ändrar returndu name egenskapen till $return i function.json.

{
  "type": "http",
  "direction": "out",
  "name": "$return"
}

I det här fallet bör funktionen se ut som i följande exempel:

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    // You can call and await an async method here
    return {
        body: "Hello, world!"
    };
}

Bindningar

I JavaScript konfigureras och definieras bindningar i en funktions function.json. Funktioner interagerar med bindningar på flera olika sätt.

Indata

Indata delas in i två kategorier i Azure Functions: den ena är utlösarindata och den andra är ytterligare indata. Utlösare och andra indatabindningar (bindningar av direction === "in") kan läsas av en funktion på tre sätt:

  • [Rekommenderas] Som parametrar som skickas till din funktion. De skickas till funktionen i samma ordning som de definieras i function.json. Egenskapen name som definieras i function.json behöver inte matcha namnet på parametern, även om den borde det.

    module.exports = async function(context, myTrigger, myInput, myOtherInput) { ... };
    
  • Som medlemmar i context.bindings objektet. Varje medlem namnges av egenskapen name som definieras i 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);
    };
    

Utdata

Utdata (bindningar av direction === "out") kan skrivas till av en funktion på flera olika sätt. I samtliga fall name motsvarar egenskapen för bindningen enligt definitionen i function.json namnet på objektmedlemmen som skrivits till i din funktion.

Du kan tilldela data till utdatabindningar på något av följande sätt (kombinera inte dessa metoder):

  • [Rekommenderas för flera utdata] Returnerar ett objekt. Om du använder en async/Promise-returneringsfunktion kan du returnera ett objekt med tilldelade utdata. I exemplet nedan heter utdatabindningarna "httpResponse" och "queueOutput" i function.json.

    module.exports = async function(context) {
        let retMsg = 'Hello, world!';
        return {
            httpResponse: {
                body: retMsg
            },
            queueOutput: retMsg
        };
    };
    
  • [Rekommenderas för enkla utdata] Returnerar ett värde direkt och använder $return bindningsnamn. Detta fungerar bara för async/Promise-returneringsfunktioner. Se exempel när du exporterar en asynkron funktion.

  • Tilldela värden till context.bindings Du kan tilldela värden direkt till context.bindings.

    module.exports = async function(context) {
        let retMsg = 'Hello, world!';
        context.bindings.httpResponse = {
            body: retMsg
        };
        context.bindings.queueOutput = retMsg;
    };
    

Datatyp för bindningar

Om du vill definiera datatypen för en indatabindning använder du dataType egenskapen i bindningsdefinitionen. Om du till exempel vill läsa innehållet i en HTTP-begäran i binärt format använder du typen binary:

{
    "type": "httpTrigger",
    "name": "req",
    "direction": "in",
    "dataType": "binary"
}

Alternativen för dataType är: binary, streamoch string.

kontextobjekt

Körningen använder ett context -objekt för att skicka data till och från din funktion och körningen. Objektet används för att läsa och ange data från bindningar och för att skriva till loggar och context är alltid den första parametern som skickas till en funktion.

module.exports = async function(context){

    // function logic goes here

    context.log("The function has executed.");
};

Kontexten som skickas till funktionen exponerar en executionContext egenskap, som är ett objekt med följande egenskaper:

Egenskapsnamn Typ Description
invocationId Sträng Tillhandahåller en unik identifierare för det specifika funktionsanropet.
functionName Sträng Anger namnet på den funktion som körs
functionDirectory Sträng Tillhandahåller funktionsappkatalogen.

I följande exempel visas hur du returnerar invocationId.

module.exports = async function (context, req) {
    context.res = {
        body: context.executionContext.invocationId
    };
};

egenskapen context.bindings

context.bindings

Returnerar ett namngivet objekt som används för att läsa eller tilldela bindningsdata. Indata och utlösarbindningsdata kan nås genom att läsa egenskaper på context.bindings. Utdatabindningsdata kan tilldelas genom att lägga till data i context.bindings

Med följande bindningsdefinitioner i function.json kan du till exempel komma åt innehållet i en kö från context.bindings.myInput och tilldela utdata till en kö med .context.bindings.myOutput

{
    "type":"queue",
    "direction":"in",
    "name":"myInput"
    ...
},
{
    "type":"queue",
    "direction":"out",
    "name":"myOutput"
    ...
}
// myInput contains the input data, which may have properties such as "name"
var author = context.bindings.myInput.name;
// Similarly, you can set your output data
context.bindings.myOutput = { 
        some_text: 'hello world', 
        a_number: 1 };

I en synkron funktion kan du välja att definiera bindningsdata för utdata med hjälp context.done av context.binding metoden i stället för objektet (se nedan).

context.bindingData-egenskap

context.bindingData

Returnerar ett namngivet objekt som innehåller utlösarmetadata och funktionsanropsdata (invocationId, , sys.methodNamesys.utcNow, sys.randGuid). Ett exempel på utlösarmetadata finns i det här exemplet på händelsehubbar.

context.done-metod

I 2.x, 3.x och 4.x ska funktionen markeras som asynkron även om det inte finns något väntande funktionsanrop i funktionen och funktionen inte behöver anropa context.done för att indikera slutet på funktionen.

//you don't need an awaited function call inside to use async
module.exports = async function (context, req) {
    context.log("you don't need an awaited function call inside to use async")
};

context.log-metod

context.log(message)

Gör att du kan skriva till strömningsfunktionsloggarna på standardspårningsnivån, med andra tillgängliga loggningsnivåer. Spårningsloggning beskrivs i detalj i nästa avsnitt.

Skriva spårningsutdata till loggar

I Functions använder context.log du metoderna för att skriva spårningsutdata till loggarna och konsolen. När du anropar context.log()skrivs meddelandet till loggarna på standardspårningsnivån, vilket är informationsspårningsnivån. Functions integreras med Azure Application Insights för att bättre avbilda dina funktionsapploggar. Application Insights, som är en del av Azure Monitor, tillhandahåller funktioner för insamling, visuell återgivning och analys av både programtelemetri och dina spårningsutdata. Mer information finns i övervakning Azure Functions.

I följande exempel skrivs en logg på informationsspårningsnivå, inklusive anrops-ID:

context.log("Something has happened. " + context.invocationId); 

Alla context.log metoder stöder samma parameterformat som stöds av metoden Node.js util.format. Överväg följande kod, som skriver funktionsloggar med hjälp av standardspårningsnivån:

context.log('Node.js HTTP trigger function processed a request. RequestUri=' + req.originalUrl);
context.log('Request Headers = ' + JSON.stringify(req.headers));

Du kan också skriva samma kod i följande format:

context.log('Node.js HTTP trigger function processed a request. RequestUri=%s', req.originalUrl);
context.log('Request Headers = ', JSON.stringify(req.headers));

Anteckning

Använd console.log inte för att skriva spårningsutdata. Eftersom utdata från console.log samlas in på funktionsappnivå är det inte kopplat till ett specifikt funktionsanrop och visas inte i en specifik funktions loggar. Version 1.x av Functions-körningen stöder inte heller användning av console.log för att skriva till konsolen.

Spårningsnivåer

Utöver standardnivån är följande loggningsmetoder tillgängliga som gör att du kan skriva funktionsloggar på specifika spårningsnivåer.

Metod Beskrivning
context.log.error(message) Skriver en händelse på felnivå till loggarna.
context.log.warn(message) Skriver en händelse på varningsnivå till loggarna.
context.log.info(meddelande) Skriver till loggning på informationsnivå eller lägre.
context.log.verbose(message) Skriver till utförlig nivåloggning.

I följande exempel skrivs samma logg på varningsspårningsnivå i stället för informationsnivån:

context.log.warn("Something has happened. " + context.invocationId); 

Eftersom felet är den högsta spårningsnivån skrivs den här spårningen till utdata på alla spårningsnivåer så länge loggningen är aktiverad.

Konfigurera spårningsnivån för loggning

Med Functions kan du definiera tröskelvärdet för spårningsnivå för skrivning till loggarna eller konsolen. De specifika tröskelinställningarna beror på din version av Functions-körningen.

Om du vill ange tröskelvärdet för spårningar som skrivits till loggarna använder du logging.logLevel egenskapen i filen host.json. Med det här JSON-objektet kan du definiera ett standardtröskelvärde för alla funktioner i funktionsappen, plus att du kan definiera specifika tröskelvärden för enskilda funktioner. Mer information finns i Så här konfigurerar du övervakning för Azure Functions.

Logga anpassad telemetri

Som standard skriver Functions utdata som spårningar till Application Insights. Om du vill ha mer kontroll kan du i stället använda Application Insights Node.js SDK för att skicka anpassade telemetridata till din Application Insights-instans.

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

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    // Use this with 'tagOverrides' to correlate custom telemetry 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});
};

Parametern tagOverrides anger operation_Id till funktionens anrops-ID. Med den här inställningen kan du korrelera all automatiskt genererad och anpassad telemetri för ett visst funktionsanrop.

HTTP-utlösare och bindningar

HTTP- och webhook-utlösare och HTTP-utdatabindningar använder begärande- och svarsobjekt för att representera HTTP-meddelanden.

Begär objekt

Objektet context.req (begäran) har följande egenskaper:

Egenskap Beskrivning
Kroppen Ett objekt som innehåller brödtexten i begäran.
Headers Ett objekt som innehåller begärandehuvudena.
Metod HTTP-metoden för begäran.
originalUrl URL:en för begäran.
Params Ett objekt som innehåller routningsparametrarna för begäran.
query Ett objekt som innehåller frågeparametrarna.
rawBody Brödtexten i meddelandet som en sträng.

Svarsobjekt

Objektet context.res (svar) har följande egenskaper:

Egenskap Beskrivning
Kroppen Ett objekt som innehåller svarets brödtext.
Headers Ett objekt som innehåller svarsrubrikerna.
isRaw Anger att formateringen hoppas över för svaret.
Status HTTP-statuskoden för svaret.
Cookies En matris med HTTP-cookieobjekt som anges i svaret. Ett HTTP-cookieobjekt har egenskaperna name, valueoch andra cookies, till exempel maxAge eller sameSite.

Åtkomst till begäran och svar

När du arbetar med HTTP-utlösare kan du komma åt HTTP-begärande- och svarsobjekten på flera olika sätt:

  • Från req och res egenskaper för objektet context . På så sätt kan du använda det konventionella mönstret för att komma åt HTTP-data från kontextobjektet i stället för att behöva använda det fullständiga context.bindings.name mönstret. I följande exempel visas hur du kommer åt objekten req och rescontext:

    // You can access your HTTP request off the context ...
    if(context.req.body.emoji === ':pizza:') context.log('Yay!');
    // and also set your HTTP response
    context.res = { status: 202, body: 'You successfully ordered more coffee!' }; 
    
  • Från de namngivna indata- och utdatabindningarna. På så sätt fungerar HTTP-utlösaren och bindningarna på samma sätt som andra bindningar. I följande exempel anges svarsobjektet med hjälp av en namngiven response bindning:

    {
        "type": "http",
        "direction": "out",
        "name": "response"
    }
    
    context.bindings.response = { status: 201, body: "Insert succeeded." };
    
  • [Endast svar] Genom att anropa context.res.send(body?: any). Ett HTTP-svar skapas med indata body som svarstext. context.done() kallas implicit.

  • [Endast svar] Genom att returnera svaret. Med ett särskilt bindningsnamn $return kan du tilldela funktionens returvärde till utdatabindningen. Följande HTTP-utdatabindning definierar en $return utdataparameter:

    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
    

    I en 2.x+-funktion kan du returnera svarsobjektet direkt:

    return { status: 201, body: "Insert succeeded." };
    

Begärande- och svarsnycklarna är i gemener.

Skalning och samtidighet

Som standard övervakar Azure Functions automatiskt belastningen på ditt program och skapar ytterligare värdinstanser för Node.js efter behov. Funktioner använder inbyggda (inte användarkonfigurerbara) tröskelvärden för olika utlösartyper för att bestämma när instanser ska läggas till, till exempel ålder på meddelanden och köstorlek för QueueTrigger. Mer information finns i Så här fungerar förbruknings- och Premium-abonnemangen.

Det här skalningsbeteendet räcker för många Node.js program. För CPU-bundna program kan du förbättra prestanda ytterligare med hjälp av flera språkprocesser.

Som standard har varje Functions-värdinstans en enda språkarbetsprocess. Du kan öka antalet arbetsprocesser per värd (upp till 10) med hjälp av FUNCTIONS_WORKER_PROCESS_COUNT programinställning. Azure Functions försöker sedan distribuera samtidiga funktionsanrop jämnt mellan dessa arbetare. Detta gör det mindre troligt att en CPU-intensiv funktion blockerar andra funktioner från att köras.

Den FUNCTIONS_WORKER_PROCESS_COUNT gäller för varje värd som Functions skapar när du skalar ut ditt program för att möta efterfrågan.

Nodversion

I följande tabell visas aktuella Node.js versioner som stöds för varje huvudversion av Functions-körningen efter operativsystem:

Functions-version Nodversion (Windows) Nodversion (Linux)
4.x (rekommenderas) ~18(förhandsversion)
~16
~14
node|18(förhandsversion)
node|16
node|14
3.x ~14
~12
~10
node|14
node|12
node|10
2.x ~12
~10
~8
node|10
node|8
1.x 6.11.2 (låst av körningen) saknas

Du kan se den aktuella versionen som körningen använder genom att logga process.version från valfri funktion.

Ange Node-versionen

För Windows-funktionsappar riktar du in versionen i Azure genom att ange appinställningenWEBSITE_NODE_DEFAULT_VERSION till en LTS-version som stöds, till exempel ~16.

Mer information om Azure Functions runtime-supportprincip finns i den här artikeln.

Beroendehantering

För att kunna använda communitybibliotek i JavaScript-koden, som visas i exemplet nedan, måste du se till att alla beroenden är installerade på din funktionsapp i Azure.

// Import the underscore.js library
const _ = require('underscore');

module.exports = async function(context) {
    // Using our imported underscore.js library
    const matched_names = _
        .where(context.bindings.myInput.names, {first: 'Carla'});
}

Anteckning

Du bör definiera en package.json fil i roten för funktionsappen. Genom att definiera filen kan alla funktioner i appen dela samma cachelagrade paket, vilket ger bästa möjliga prestanda. Om en versionskonflikt uppstår kan du lösa det genom att lägga till en package.json fil i mappen för en specifik funktion.

När du distribuerar funktionsappar från källkontrollen utlöser alla package.json filer som finns på lagringsplatsen en npm install i mappen under distributionen. Men när du distribuerar via portalen eller CLI måste du installera paketen manuellt.

Det finns två sätt att installera paket på funktionsappen:

Distribuera med beroenden

  1. Installera alla nödvändiga paket lokalt genom att köra npm install.

  2. Distribuera koden och se till att node_modules mappen ingår i distributionen.

Använda Kudu (endast Windows)

  1. Gå till https://<function_app_name>.scm.azurewebsites.net.

  2. Välj Felsökkonsol-CMD>.

  3. Gå till D:\home\site\wwwrootoch dra sedan filen package.json till mappen wwwroot längst upp på sidan.
    Du kan ladda upp filer till funktionsappen på andra sätt också. Mer information finns i Så här uppdaterar du funktionsappfiler.

  4. När filen package.json har laddats upp kör du npm install kommandot i Kudu-fjärrkörningskonsolen.
    Den här åtgärden laddar ned paketen som anges i filen package.json och startar om funktionsappen.

Miljövariabler

Lägg till egna miljövariabler i en funktionsapp, både i lokala miljöer och molnmiljöer, till exempel drifthemligheter (anslutningssträngar, nycklar och slutpunkter) eller miljöinställningar (till exempel profileringsvariabler). Få åtkomst till de här inställningarna med hjälp av process.env i funktionskoden.

I lokal utvecklingsmiljö

När du kör lokalt innehåller funktionsprojektet en local.settings.json fil där du lagrar dina miljövariabler i Values objektet.

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "translatorTextEndPoint": "https://api.cognitive.microsofttranslator.com/",
    "translatorTextKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "languageWorkers__node__arguments": "--prof"
  }
}

I Azure-molnmiljö

När du kör i Azure kan du med funktionsappen ange och använda programinställningar, till exempel tjänstanslutningssträngar, och exponerar dessa inställningar som miljövariabler under körningen.

Det finns flera sätt att lägga till, uppdatera och ta bort funktionsappinställningar:

Ändringar i funktionsappsinställningarna kräver att funktionsappen startas om.

Åtkomst till miljövariabler i kod

Få åtkomst till programinställningar som miljövariabler med , process.envsom du ser här i det andra och tredje anropet AzureWebJobsStorage till context.log() där vi loggar miljövariablerna ochWEBSITE_SITE_NAME:

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

ECMAScript-moduler (förhandsversion)

Anteckning

Eftersom ECMAScript-moduler för närvarande är en förhandsversionsfunktion i Node.js 14 och 16 Azure Functions.

ECMAScript-moduler (ES-moduler) är det nya officiella standardmodulsystemet för Node.js. Hittills använder kodexemplen i den här artikeln CommonJS-syntaxen. När du kör Azure Functions i Node.js 14 eller senare kan du välja att skriva dina funktioner med ES-modulsyntax.

Om du vill använda ES-moduler i en funktion ändrar du dess filnamn så att det använder ett .mjs tillägg. Följande index.mjs-filexempel är en HTTP-utlöst funktion som använder ES-modulers syntax för att importera uuid biblioteket och returnera ett värde.

import { v4 as uuidv4 } from 'uuid';

export default async function (context, req) {
    context.res.body = uuidv4();
};

Konfigurera funktionsinmatningspunkt

Egenskaperna function.jsonscriptFile och entryPoint kan användas för att konfigurera platsen och namnet på den exporterade funktionen. Dessa egenskaper kan vara viktiga när JavaScript överförs.

Använda scriptFile

Som standard körs en JavaScript-funktion från index.js, en fil som delar samma överordnade katalog som motsvarande function.json.

scriptFile kan användas för att hämta en mappstruktur som ser ut som i följande exempel:

FunctionApp
 | - host.json
 | - myNodeFunction
 | | - function.json
 | - lib
 | | - sayHello.js
 | - node_modules
 | | - ... packages ...
 | - package.json

För function.jsonmyNodeFunction bör innehålla en scriptFile egenskap som pekar på filen med den exporterade funktionen som ska köras.

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

Använda entryPoint

I scriptFile (eller index.js) måste en funktion exporteras med module.exports för att hittas och köras. Som standard är den funktion som körs när den utlöses den enda exporten från filen, exporten med namnet runeller exporten med namnet index.

Detta kan konfigureras med i entryPointfunction.json, som i följande exempel:

{
  "entryPoint": "logFoo",
  "bindings": [
    ...
  ]
}

I Functions v2.x eller senare, som stöder parametern this i användarfunktioner, kan funktionskoden sedan vara som i följande exempel:

class MyObj {
    constructor() {
        this.foo = 1;
    };

    async logFoo(context) { 
        context.log("Foo is " + this.foo); 
    }
}

const myObj = new MyObj();
module.exports = myObj;

I det här exemplet är det viktigt att observera att även om ett objekt exporteras finns det inga garantier för att bevara tillståndet mellan körningarna.

Lokal felsökning

När den startas med parametern --inspect lyssnar en Node.js process efter en felsökningsklient på den angivna porten. I Azure Functions 2.x eller senare kan du ange argument som ska skickas till Node.js process som kör koden genom att lägga till miljövariabeln eller appinställningen languageWorkers:node:arguments = <args>.

Om du vill felsöka lokalt lägger du till "languageWorkers:node:arguments": "--inspect=5858" under Values i filen local.settings.json och bifogar ett felsökningsprogram till port 5858.

Vid felsökning med VS Code läggs parametern --inspect automatiskt till med hjälp av port värdet i projektets launch.json-fil.

I version 1.x fungerar inte inställningen languageWorkers:node:arguments . Felsökningsporten kan väljas med parametern --nodeDebugPort på Azure Functions Core Tools.

Anteckning

Du kan bara konfigurera languageWorkers:node:arguments när du kör funktionsappen lokalt.

Testning

Testningen av dina funktioner omfattar:

  • HTTP från slutpunkt till slutpunkt: Om du vill testa en funktion från dess HTTP-slutpunkt kan du använda valfritt verktyg som kan göra en HTTP-begäran, till exempel cURL, Postman eller JavaScripts hämtningsmetod.

  • Integreringstestning: Integrationstestet innehåller funktionsapplagret. Den här testningen innebär att du måste kontrollera parametrarna i funktionen, inklusive begäran och kontexten. Kontexten är unik för varje typ av utlösare och innebär att du behöver känna till inkommande och utgående bindningar för den utlösartypen.

    Läs mer om integreringstestning och modellering av kontextskiktet med en experimentell GitHub-lagringsplats, https://github.com/anthonychu/azure-functions-test-utils.

  • Enhetstestning: Enhetstestning utförs i funktionsappen. Du kan använda valfritt verktyg som kan testa JavaScript, till exempel Jest eller Mocha.

TypeScript

När du använder version 2.x eller senare av Functions-körningen kan du använda både Azure Functions för Visual Studio Code och Azure Functions Core Tools för att skapa funktionsappar med hjälp av en mall som stöder TypeScript-funktionsappprojekt. Mallen genererar package.json och tsconfig.json projektfiler som gör det enklare att transpilera, köra och publicera JavaScript-funktioner från TypeScript-kod med dessa verktyg.

En genererad .funcignore fil används för att ange vilka filer som undantas när ett projekt publiceras till Azure.

TypeScript-filer (.ts) överförs till JavaScript-filer (.js) i utdatakatalogen dist . TypeScript-mallar använder parameternscriptFile i function.json för att ange platsen för motsvarande .js fil i dist mappen. Utdataplatsen anges av mallen med hjälp outDir av parametern tsconfig.json i filen . Om du ändrar den här inställningen eller namnet på mappen kan körningen inte hitta koden som ska köras.

Hur du utvecklar och distribuerar lokalt från ett TypeScript-projekt beror på ditt utvecklingsverktyg.

Visuell Studio-kod

Med Azure Functions för Visual Studio Code-tillägget kan du utveckla dina funktioner med hjälp av TypeScript. Core Tools är ett krav för tillägget Azure Functions.

Om du vill skapa en TypeScript-funktionsapp i Visual Studio Code väljer du TypeScript som språk när du skapar en funktionsapp.

När du trycker på F5 för att köra appen lokalt görs transpileringen innan värden (func.exe) initieras.

När du distribuerar funktionsappen till Azure med knappen Distribuera till funktionsapp... genererar Azure Functions tillägget först en produktionsklar version av JavaScript-filer från TypeScript-källfilerna.

Azure Functions Core Tools

Det finns flera sätt på vilka ett TypeScript-projekt skiljer sig från ett JavaScript-projekt när du använder Core Tools.

Skapa projekt

Om du vill skapa ett TypeScript-funktionsappprojekt med Core Tools måste du ange språkalternativet TypeScript när du skapar funktionsappen. Du kan göra detta på något av följande sätt:

  • func init Kör kommandot, välj node som språkstack och välj typescriptsedan .

  • Kör kommandot func init --worker-runtime typescript.

Kör lokalt

Om du vill köra funktionsappkoden lokalt med Core Tools använder du följande kommandon i stället func host startför :

npm install
npm start

Kommandot npm start motsvarar följande kommandon:

  • npm run build
  • func extensions install
  • tsc
  • func start

Publicera till Azure

Innan du använder func azure functionapp publish kommandot för att distribuera till Azure skapar du en produktionsklar version av JavaScript-filer från TypeScript-källfilerna.

Följande kommandon förbereder och publicerar ditt TypeScript-projekt med core tools:

npm run build:production 
func azure functionapp publish <APP_NAME>

I det här kommandot ersätter du <APP_NAME> med namnet på din funktionsapp.

Överväganden för JavaScript-funktioner

När du arbetar med JavaScript-funktioner bör du vara medveten om övervägandena i följande avsnitt.

Välj enstaka vCPU-App Service planer

När du skapar en funktionsapp som använder App Service plan rekommenderar vi att du väljer en plan med en enda vCPU i stället för en plan med flera virtuella processorer. I dag kör Functions JavaScript-funktioner mer effektivt på virtuella datorer med en virtuell dator med en virtuell dator, och att använda större virtuella datorer ger inte förväntade prestandaförbättringar. Om det behövs kan du skala ut manuellt genom att lägga till fler vm-instanser med en enda vCPU, eller så kan du aktivera autoskalning. Mer information finns i Skala antalet instanser manuellt eller automatiskt.

Kallstart

När du utvecklar Azure Functions i den serverlösa värdmodellen är kallstarter en realitet. Kallstart syftar på det faktum att det tar längre tid att starta när funktionsappen startar för första gången efter en period av inaktivitet. För JavaScript-funktioner med stora beroendeträd i synnerhet kan kallstart vara betydande. Om du vill påskynda kallstartsprocessen kör du dina funktioner som en paketfil när det är möjligt. Många distributionsmetoder använder körningen från paketmodellen som standard, men om du upplever stora kallstarter och inte körs på det här sättet kan den här ändringen ge en betydande förbättring.

Anslutningsgränser

När du använder en tjänstspecifik klient i ett Azure Functions program ska du inte skapa en ny klient med varje funktionsanrop. Skapa i stället en enda statisk klient i det globala omfånget. Mer information finns i Hantera anslutningar i Azure Functions.

Använd async och await

När du skriver Azure Functions i JavaScript bör du skriva kod med nyckelorden async och await . Genom att skriva kod med och asyncawait i stället för återanrop eller .then med .catch Promises kan du undvika två vanliga problem:

  • Utlösa ohanterade undantag som kraschar Node.js processen, vilket kan påverka körningen av andra funktioner.
  • Oväntat beteende, till exempel saknade loggar från context.log, som orsakas av asynkrona anrop som inte väntar ordentligt.

I exemplet nedan anropas den asynkrona metoden fs.readFile med en felinriktad återanropsfunktion som den andra parametern. Den här koden orsakar båda problemen som nämns ovan. Ett undantag som inte uttryckligen fångas i rätt omfång kraschade hela processen (problem nr 1). Att anropa 1.x context.done() utanför omfånget för återanropsfunktionen innebär att funktionsanropet kan sluta innan filen läss (problem 2). I det här exemplet resulterar anrop av 1.x context.done() för tidigt i saknade loggposter som börjar med 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();
}

Genom att använda nyckelorden async och await undviker du båda dessa fel. Du bör använda Node.js-verktygsfunktionen util.promisify för att omvandla funktioner av typen error-first callback till inväntningsbara funktioner.

I exemplet nedan misslyckas alla ohanterade undantag som utlöses under funktionskörningen endast det enskilda anropet som utlöste ett undantag. Nyckelordet await innebär att stegen som följer readFileAsync endast körs när readFile har slutförts. Med async och awaitbehöver du inte heller anropa återanropet context.done() .

// Recommended pattern
const fs = require('fs');
const util = require('util');
const readFileAsync = util.promisify(fs.readFile);

module.exports = async function (context) {
    let data;
    try {
        data = await readFileAsync('./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}`);
}

Nästa steg

Mer information finns i följande resurser: