Przewodnik dewelopera dotyczący usługi Azure Functions Node.js

Ten przewodnik stanowi wprowadzenie do tworzenia usługi Azure Functions przy użyciu języka JavaScript lub TypeScript. W tym artykule założono, że znasz już przewodnik dewelopera usługi Azure Functions.

Ważne

Zawartość tego artykułu zmienia się w zależności od wybranego modelu programowania Node.js w selektorze w górnej części tej strony. Wybrana wersja powinna być zgodna z wersją pakietu npm używanego @azure/functions w aplikacji. Jeśli nie masz tego pakietu wymienionego w pliku package.json, wartość domyślna to v3. Dowiedz się więcej o różnicach między wersjami 3 i v4 w przewodniku migracji.

Jako deweloper Node.js możesz również zainteresować się jednym z następujących artykułów:

Wprowadzenie Pojęcia Nauka krok po kroku

Kwestie wymagające rozważenia

  • Model programowania Node.js nie powinien być mylony ze środowiskiem uruchomieniowym usługi Azure Functions:
    • Model programowania: definiuje sposób tworzenia kodu i jest specyficzny dla języków JavaScript i TypeScript.
    • Środowisko uruchomieniowe: definiuje podstawowe zachowanie usługi Azure Functions i jest współużytkowane we wszystkich językach.
  • Wersja modelu programowania jest ściśle powiązana z wersją @azure/functions pakietu npm. Jest ona wersjonowana niezależnie od środowiska uruchomieniowego. Zarówno środowisko uruchomieniowe, jak i model programowania używają numeru 4 jako najnowszej wersji głównej, ale to zbieg okoliczności.
  • Nie można mieszać modeli programowania w wersji 3 i 4 w tej samej aplikacji funkcji. Po zarejestrowaniu jednej funkcji w wersji 4 w aplikacji wszystkie funkcje w wersji 3 zarejestrowane w plikach function.json są ignorowane.

Obsługiwane wersje

W poniższej tabeli przedstawiono każdą wersję modelu programowania Node.js wraz z obsługiwanymi wersjami środowiska uruchomieniowego usługi Azure Functions i Node.js.

Wersja modelu programowania Poziom pomocy technicznej Wersja środowiska uruchomieniowego usługi Functions wersja Node.js opis
4.x Ogólna dostępność 4.25+ 20.x, 18.x Obsługuje elastyczną strukturę plików i podejście skoncentrowane na kodzie do wyzwalaczy i powiązań.
3.x Ogólna dostępność 4.x 20.x, 18.x, 16.x, 14.x Wymaga określonej struktury plików z wyzwalaczami i powiązaniami zadeklarowanymi w pliku "function.json"
2.x nie dotyczy 3.x 14.x, 12.x, 10.x 13 grudnia 2022 r. osiągnięto koniec wsparcia. Aby uzyskać więcej informacji, zobacz Wersje usługi Functions.
1.x nie dotyczy 2.x 10.x, 8.x 13 grudnia 2022 r. osiągnięto koniec wsparcia. Aby uzyskać więcej informacji, zobacz Wersje usługi Functions.

Struktura folderów

Wymagana struktura folderów dla projektu JavaScript wygląda następująco:

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

Główny folder projektu, <project_root>, może zawierać następujące pliki:

  • .vscode/: (Opcjonalnie) Zawiera przechowywaną konfigurację programu Visual Studio Code. Aby dowiedzieć się więcej, zobacz Ustawienia programu Visual Studio Code.
  • myFirstFunction/function.json: zawiera konfigurację wyzwalacza, danych wejściowych i wyjściowych funkcji. Nazwa katalogu określa nazwę funkcji.
  • myFirstFunction/index.js: przechowuje kod funkcji. Aby zmienić tę domyślną ścieżkę pliku, zobacz using scriptFile (Używanie pliku scriptFile).
  • .funcignore: (Opcjonalnie) Deklaruje pliki, które nie powinny być publikowane na platformie Azure. Zazwyczaj ten plik zawiera plik vscode/ , aby zignorować ustawienie edytora, przetestować/ zignorować przypadki testowe i local.settings.json , aby zapobiec publikowaniu ustawień aplikacji lokalnych.
  • host.json: zawiera opcje konfiguracji, które mają wpływ na wszystkie funkcje w wystąpieniu aplikacji funkcji. Ten plik jest publikowany na platformie Azure. Nie wszystkie opcje są obsługiwane w przypadku uruchamiania lokalnego. Aby dowiedzieć się więcej, zobacz host.json.
  • local.settings.json: służy do przechowywania ustawień aplikacji i parametry połączenia, gdy są uruchomione lokalnie. Ten plik nie jest publikowany na platformie Azure. Aby dowiedzieć się więcej, zobacz local.settings.file.
  • package.json: zawiera opcje konfiguracji, takie jak lista zależności pakietów, główny punkt wejścia i skrypty.

Zalecana struktura folderów dla projektu JavaScript wygląda następująco:

<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

Główny folder projektu, <project_root>, może zawierać następujące pliki:

  • .vscode/: (Opcjonalnie) Zawiera przechowywaną konfigurację programu Visual Studio Code. Aby dowiedzieć się więcej, zobacz Ustawienia programu Visual Studio Code.
  • src/functions/: domyślna lokalizacja wszystkich funkcji i powiązanych wyzwalaczy i powiązań.
  • test/: (Opcjonalnie) Zawiera przypadki testowe aplikacji funkcji.
  • .funcignore: (Opcjonalnie) Deklaruje pliki, które nie powinny być publikowane na platformie Azure. Zazwyczaj ten plik zawiera plik vscode/ , aby zignorować ustawienie edytora, przetestować/ zignorować przypadki testowe i local.settings.json , aby zapobiec publikowaniu ustawień aplikacji lokalnych.
  • host.json: zawiera opcje konfiguracji, które mają wpływ na wszystkie funkcje w wystąpieniu aplikacji funkcji. Ten plik jest publikowany na platformie Azure. Nie wszystkie opcje są obsługiwane w przypadku uruchamiania lokalnego. Aby dowiedzieć się więcej, zobacz host.json.
  • local.settings.json: służy do przechowywania ustawień aplikacji i parametry połączenia, gdy są uruchomione lokalnie. Ten plik nie jest publikowany na platformie Azure. Aby dowiedzieć się więcej, zobacz local.settings.file.
  • package.json: zawiera opcje konfiguracji, takie jak lista zależności pakietów, główny punkt wejścia i skrypty.

Rejestrowanie funkcji

Model w wersji 3 rejestruje funkcję na podstawie istnienia dwóch plików. Najpierw potrzebny function.json jest plik znajdujący się w folderze o jeden poziom w dół od katalogu głównego aplikacji. Po drugie, potrzebny jest plik JavaScript, który eksportuje funkcję. Domyślnie model szuka index.js pliku w tym samym folderze co plik function.json. Jeśli używasz języka TypeScript, musisz użyć scriptFile właściwości w pliku , function.json aby wskazać skompilowany plik JavaScript. Aby dostosować lokalizację pliku lub nazwę eksportu funkcji, zobacz konfigurowanie punktu wejścia funkcji.

Eksportowana funkcja powinna być zawsze zadeklarowana jako element async function w modelu w wersji 3. Można wyeksportować funkcję synchroniczną, ale następnie należy wywołać context.done() metodę , aby zasygnalizować, że funkcja została ukończona, co jest przestarzałe i nie jest zalecane.

Funkcja jest przekazywana wywołanie context jako pierwszy argument i dane wejściowe jako pozostałe argumenty.

Poniższy przykład to prosta funkcja, która rejestruje, że została wyzwolona i odpowiada za pomocą polecenia 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!' };
};

Model programowania ładuje funkcje na main podstawie pola w obiekcie package.json. Pole można ustawić main na jeden plik lub wiele plików przy użyciu wzorca glob. W poniższej main tabeli przedstawiono przykładowe wartości pola:

Przykład opis
src/index.js Rejestrowanie funkcji z jednego pliku głównego.
src/functions/*.js Zarejestruj każdą funkcję z własnego pliku.
src/{index.js,functions/*.js} Kombinacja, w której rejestrujesz każdą funkcję z własnego pliku, ale nadal masz plik główny ogólnego kodu na poziomie aplikacji.

Aby zarejestrować funkcję, należy zaimportować app obiekt z modułu @azure/functions npm i wywołać metodę specyficzną dla typu wyzwalacza. Pierwszym argumentem podczas rejestrowania funkcji jest nazwa funkcji. Drugim argumentem jest obiekt określający konfigurację options wyzwalacza, programu obsługi i innych danych wejściowych lub wyjściowych. W niektórych przypadkach, gdy konfiguracja wyzwalacza nie jest konieczna, można przekazać program obsługi bezpośrednio jako drugi argument zamiast options obiektu.

Zarejestrowanie funkcji można wykonać z dowolnego pliku w projekcie, o ile plik jest ładowany (bezpośrednio lub pośrednio) na main podstawie pola w package.json pliku. Funkcja powinna być zarejestrowana w zakresie globalnym, ponieważ nie można rejestrować funkcji po rozpoczęciu wykonywania.

Poniższy przykład to prosta funkcja, która rejestruje, że została wyzwolona i odpowiada za pomocą polecenia 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!' };
    }
});

Dane wejściowe i wyjściowe

Funkcja jest wymagana, aby mieć dokładnie jedno podstawowe dane wejściowe nazywane wyzwalaczem. Może również mieć pomocnicze dane wejściowe i/lub wyjściowe. Dane wejściowe i wyjściowe są konfigurowane w plikach function.json , a także nazywane powiązaniami.

Dane wejściowe

Dane wejściowe są powiązaniami z direction ustawieniem in. Główną różnicą między wyzwalaczem a pomocniczym wejściem jest to, że type wyzwalacz kończy się na Trigger, na przykład typ a typem blobTriggerblob. Większość funkcji używa tylko wyzwalacza, a nie wiele pomocniczych typów danych wejściowych jest obsługiwanych.

Dostęp do danych wejściowych można uzyskać na kilka sposobów:

  • [Zalecane] Jako argumenty przekazywane do funkcji: użyj argumentów w tej samej kolejności, w której są zdefiniowane w pliku function.json. Właściwość zdefiniowana name w pliku function.json nie musi być zgodna z nazwą argumentu, chociaż jest zalecana dla dobra organizacji.

    module.exports = async function (context, myTrigger, myInput, myOtherInput) { ... };
    
  • Jako właściwości context.bindings: użyj klucza pasującego do właściwości zdefiniowanej name w pliku 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);
    };
    

Dane wyjściowe

Dane wyjściowe są powiązaniami z direction ustawieniem i out można je ustawić na kilka sposobów:

  • [Zalecane w przypadku pojedynczych danych wyjściowych] Zwróć wartość bezpośrednio: jeśli używasz funkcji asynchronicznych, możesz zwrócić tę wartość bezpośrednio. Należy zmienić name właściwość powiązania wyjściowego na $return w function.json następujący przykład:

    {
        "name": "$return",
        "type": "http",
        "direction": "out"
    }
    
    module.exports = async function (context, request) {
        return {
            body: "Hello, world!"
        };
    }
    
  • [Zalecane dla wielu danych wyjściowych] Zwróć obiekt zawierający wszystkie dane wyjściowe: jeśli używasz funkcji asynchronicznych, możesz zwrócić obiekt z właściwością zgodną z nazwą każdego powiązania w obiekcie function.json. W poniższym przykładzie użyto powiązań wyjściowych o nazwach "httpResponse" i "queueOutput":

    {
        "name": "httpResponse",
        "type": "http",
        "direction": "out"
    },
    {
        "name": "queueOutput",
        "type": "queue",
        "direction": "out",
        "queueName": "helloworldqueue",
        "connection": "storage_APPSETTING"
    }
    
    module.exports = async function (context, request) {
        let message = 'Hello, world!';
        return {
            httpResponse: {
                body: message
            },
            queueOutput: message
        };
    };
    
  • Ustaw wartości na : context.bindings jeśli nie używasz funkcji asynchronicznych lub nie chcesz używać poprzednich opcji, możesz ustawić wartości bezpośrednio w context.bindingsobiekcie , gdzie klucz jest zgodny z nazwą powiązania. W poniższym przykładzie użyto powiązań wyjściowych o nazwach "httpResponse" i "queueOutput":

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

Typ danych powiązań

Możesz użyć właściwości w powiązaniu dataType wejściowym, aby zmienić typ danych wejściowych, jednak ma pewne ograniczenia:

  • W Node.js są obsługiwane tylko i stringbinary są obsługiwane (stream nie jest)
  • W przypadku danych wejściowych dataType HTTP właściwość jest ignorowana. Zamiast tego użyj właściwości w request obiekcie, aby uzyskać treść w żądanym formacie. Aby uzyskać więcej informacji, zobacz Żądanie HTTP.

W poniższym przykładzie wyzwalacza kolejki magazynu domyślny typ myQueueItem to string, ale jeśli ustawiono wartość dataTypebinary, typ zmieni się na Node.js Buffer.

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

Funkcja jest wymagana, aby mieć dokładnie jedno podstawowe dane wejściowe nazywane wyzwalaczem. Może również mieć pomocnicze dane wejściowe, podstawowe dane wyjściowe nazywane zwracane dane wyjściowe i/lub pomocnicze. Dane wejściowe i wyjściowe są również określane jako powiązania poza kontekstem modelu programowania Node.js. Przed wersją 4 modelu te powiązania zostały skonfigurowane w function.json plikach.

Wprowadzanie wyzwalacza

Wyzwalacz jest jedynym wymaganym wejściem lub wyjściem. W przypadku większości typów wyzwalaczy należy zarejestrować funkcję przy użyciu metody w app obiekcie o nazwie po typie wyzwalacza. Możesz określić konfigurację specyficzną dla wyzwalacza bezpośrednio na argumencie options . Na przykład wyzwalacz HTTP umożliwia określenie trasy. Podczas wykonywania wartość odpowiadająca temu wyzwalaczowi jest przekazywana jako pierwszy argument do programu obsługi.

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

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

Zwracanie danych wyjściowych

Zwracane dane wyjściowe są opcjonalne i w niektórych przypadkach skonfigurowane domyślnie. Na przykład wyzwalacz HTTP zarejestrowany app.http przy użyciu jest skonfigurowany do automatycznego zwracania danych wyjściowych odpowiedzi HTTP. W przypadku większości typów danych wyjściowych należy określić konfigurację zwracaną dla options argumentu z pomocą output obiektu wyeksportowanego z modułu @azure/functions . Podczas wykonywania ustawisz te dane wyjściowe, zwracając je z programu obsługi.

W poniższym przykładzie użyto wyzwalacza czasomierza i danych wyjściowych kolejki magazynu:

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

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

Dodatkowe dane wejściowe i wyjściowe

Oprócz wyzwalacza i zwracania można określić dodatkowe dane wejściowe lub wyjściowe argumentu options podczas rejestrowania funkcji. Obiekty input i output wyeksportowane z modułu @azure/functions zapewniają metody specyficzne dla typu, aby ułatwić konstruowanie konfiguracji. Podczas wykonywania otrzymujesz lub ustawiasz wartości z parametrem context.extraInputs.get lub context.extraOutputs.set, przekazując oryginalny obiekt konfiguracji jako pierwszy argument.

Poniższy przykład to funkcja wyzwalana przez kolejkę magazynu z dodatkowymi danymi wejściowymi obiektu blob magazynu skopiowanymi do dodatkowych danych wyjściowych obiektu blob magazynu. Komunikat kolejki powinien być nazwą pliku i zastąpi {queueTrigger} go nazwą obiektu blob, który ma zostać skopiowany, za pomocą wyrażenia powiązania.

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

Ogólne dane wejściowe i wyjściowe

Obiekty app, , inputtriggeri output wyeksportowane przez @azure/functions moduł udostępniają metody specyficzne dla typu dla większości typów. W przypadku wszystkich typów, które nie są obsługiwane, udostępniono metodę umożliwiającą generic ręczne określenie konfiguracji. Metodę generic można również użyć, jeśli chcesz zmienić ustawienia domyślne udostępniane przez metodę specyficzną dla typu.

Poniższy przykład to prosta funkcja wyzwalana przez protokół HTTP przy użyciu metod ogólnych zamiast metod specyficznych dla typu.

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

Kontekst wywołania

Każde wywołanie funkcji jest przekazywane obiekt wywołania, używany do odczytywania context danych wejściowych, ustawiania danych wyjściowych, zapisywania w dziennikach i odczytywania różnych metadanych. W modelu w wersji 3 obiekt kontekstu jest zawsze pierwszym argumentem przekazywanym do programu obsługi.

Obiekt context ma następujące właściwości:

Właściwości opis
invocationId Identyfikator wywołania bieżącej funkcji.
executionContext Zobacz kontekst wykonywania.
bindings Zobacz powiązania.
bindingData Metadane dotyczące danych wejściowych wyzwalacza dla tego wywołania, a nie w tym samej wartości. Na przykład wyzwalacz centrum zdarzeń ma enqueuedTimeUtc właściwość .
traceContext Kontekst śledzenia rozproszonego. Aby uzyskać więcej informacji, zobacz Trace Context.
bindingDefinitions Konfiguracja danych wejściowych i wyjściowych zgodnie z definicją w pliku function.json.
req Zobacz Żądanie HTTP.
res Zobacz Odpowiedź HTTP.

context.executionContext

Obiekt context.executionContext ma następujące właściwości:

Właściwości opis
invocationId Identyfikator wywołania bieżącej funkcji.
functionName Nazwa wywoływanej funkcji. Nazwa folderu zawierającego function.json plik określa nazwę funkcji.
functionDirectory Folder zawierający function.json plik.
retryContext Zobacz kontekst ponawiania prób.

context.executionContext.retryContext

Obiekt context.executionContext.retryContext ma następujące właściwości:

Właściwości opis
retryCount Liczba reprezentująca bieżącą próbę ponawiania próby.
maxRetryCount Maksymalna liczba ponownych prób wykonania. Wartość oznacza, aby ponowić -1 próbę na czas nieokreślony.
exception Wyjątek, który spowodował ponowienie próby.

context.bindings

Obiekt context.bindings jest używany do odczytywania danych wejściowych lub ustawiania danych wyjściowych. Poniższy przykład to wyzwalacz kolejki magazynu, który służy context.bindings do kopiowania danych wejściowych obiektu blob magazynu do danych wyjściowych obiektu blob magazynu. Zawartość komunikatu kolejki zastępuje {queueTrigger} nazwę pliku, która ma zostać skopiowana, za pomocą wyrażenia powiązania.

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

Metoda context.done jest przestarzała. Zanim funkcje asynchroniczne były obsługiwane, należy zasygnalizował, że funkcja jest wykonywana przez wywołanie metody context.done():

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

Teraz zaleca się usunięcie wywołania context.done() funkcji i oznaczenie jej jako asynchronicznych, tak aby zwracała obietnicę (nawet jeśli nic nie await zrobisz). Gdy tylko funkcja zakończy działanie (innymi słowy, zwrócona obietnica zostanie rozwiązana), model w wersji 3 wie, że funkcja jest wykonywana.

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

Każde wywołanie funkcji jest przekazywane jako obiekt wywołania context z informacjami o wywołaniu i metodach używanych do rejestrowania. W modelu context w wersji 4 obiekt jest zazwyczaj drugim argumentem przekazywanym do programu obsługi.

Klasa InvocationContext ma następujące właściwości:

Właściwości opis
invocationId Identyfikator wywołania bieżącej funkcji.
functionName Nazwa funkcji.
extraInputs Służy do pobierania wartości dodatkowych danych wejściowych. Aby uzyskać więcej informacji, zobacz dodatkowe dane wejściowe i wyjściowe.
extraOutputs Służy do ustawiania wartości dodatkowych danych wyjściowych. Aby uzyskać więcej informacji, zobacz dodatkowe dane wejściowe i wyjściowe.
retryContext Zobacz kontekst ponawiania prób.
traceContext Kontekst śledzenia rozproszonego. Aby uzyskać więcej informacji, zobacz Trace Context.
triggerMetadata Metadane dotyczące danych wejściowych wyzwalacza dla tego wywołania, a nie w tym samej wartości. Na przykład wyzwalacz centrum zdarzeń ma enqueuedTimeUtc właściwość .
options Opcje używane podczas rejestrowania funkcji po ich zweryfikowaniu i z jawnie określonymi wartościami domyślnymi.

Kontekst ponawiania prób

Obiekt retryContext ma następujące właściwości:

Właściwości opis
retryCount Liczba reprezentująca bieżącą próbę ponawiania próby.
maxRetryCount Maksymalna liczba ponownych prób wykonania. Wartość oznacza, aby ponowić -1 próbę na czas nieokreślony.
exception Wyjątek, który spowodował ponowienie próby.

Aby uzyskać więcej informacji, zobacz retry-policies.

Rejestrowanie

W usłudze Azure Functions zaleca się używanie context.log() ich do zapisywania dzienników. Usługa Azure Functions integruje się z aplikacja systemu Azure Szczegółowe informacje, aby lepiej przechwytywać dzienniki aplikacji funkcji. Szczegółowe informacje aplikacji, część usługi Azure Monitor, udostępnia funkcje zbierania, renderowania wizualnego i analizy dzienników aplikacji oraz danych wyjściowych śledzenia. Aby dowiedzieć się więcej, zobacz Monitorowanie usługi Azure Functions.

Uwaga

Jeśli używasz alternatywnej metody Node.jsconsole.log, te dzienniki są śledzone na poziomie aplikacji i nie będą skojarzone z żadną konkretną funkcją. Zdecydowanie zaleca się użycie context funkcji rejestrowania zamiast console tego, aby wszystkie dzienniki zostały skojarzone z określoną funkcją.

Poniższy przykład zapisuje dziennik na domyślnym poziomie "informacji", w tym identyfikator wywołania:

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

Poziomy rejestrowania

Oprócz metody domyślnej context.log dostępne są następujące metody, które umożliwiają zapisywanie dzienników na określonych poziomach:

Metoda opis
context.log.error() Zapisuje zdarzenie na poziomie błędu w dziennikach.
context.log.warn() Zapisuje zdarzenie na poziomie ostrzeżenia w dziennikach.
context.log.info() Zapisuje zdarzenie na poziomie informacji w dziennikach.
context.log.verbose() Zapisuje zdarzenie na poziomie śledzenia w dziennikach.
Metoda opis
context.trace() Zapisuje zdarzenie na poziomie śledzenia w dziennikach.
context.debug() Zapisuje zdarzenie na poziomie debugowania w dziennikach.
context.info() Zapisuje zdarzenie na poziomie informacji w dziennikach.
context.warn() Zapisuje zdarzenie na poziomie ostrzeżenia w dziennikach.
context.error() Zapisuje zdarzenie na poziomie błędu w dziennikach.

Konfigurowanie poziomu dziennika

Usługa Azure Functions umożliwia zdefiniowanie poziomu progu, który ma być używany podczas śledzenia i wyświetlania dzienników. Aby ustawić próg, użyj logging.logLevel właściwości w host.json pliku . Ta właściwość umożliwia zdefiniowanie domyślnego poziomu zastosowanego do wszystkich funkcji lub progu dla każdej funkcji. Aby dowiedzieć się więcej, zobacz Jak skonfigurować monitorowanie dla usługi Azure Functions.

Śledzenie danych niestandardowych

Domyślnie usługa Azure Functions zapisuje dane wyjściowe jako ślady w usłudze Application Szczegółowe informacje. Aby uzyskać większą kontrolę, możesz zamiast tego użyć zestawu SDK usługi Application Szczegółowe informacje Node.js do wysyłania danych niestandardowych do wystąpienia usługi Application Szczegółowe informacje.

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

Parametr tagOverrides ustawia operation_Id parametr na identyfikator wywołania funkcji. To ustawienie umożliwia skorelowanie wszystkich automatycznie generowanych i niestandardowych dzienników dla wywołania danej funkcji.

Wyzwalacze HTTP

Wyzwalacze HTTP i webhook używają obiektów żądań i odpowiedzi do reprezentowania komunikatów HTTP.

Wyzwalacze HTTP i webhook używają obiektów HttpRequest i HttpResponse do reprezentowania komunikatów HTTP. Klasy reprezentują podzbiór standardu pobierania undici przy użyciu pakietu Node.js.

Żądanie HTTP

Dostęp do żądania można uzyskać na kilka sposobów:

  • Jako drugi argument funkcji:

    module.exports = async function (context, request) {
        context.log(`Http function processed request for url "${request.url}"`);
    
  • context.req Z właściwości:

    module.exports = async function (context, request) {
        context.log(`Http function processed request for url "${context.req.url}"`);
    
  • Z nazwanych powiązań wejściowych: ta opcja działa tak samo jak dowolne powiązanie niezwiązane z protokołem HTTP. Nazwa powiązania w function.json pliku musi być zgodna z kluczem w context.bindingspliku lub "request1" w poniższym przykładzie:

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

Obiekt HttpRequest ma następujące właściwości:

Właściwość Type Opis
method string Metoda żądania HTTP używana do wywoływania tej funkcji.
url string Adres URL żądania.
headers Record<string, string> Nagłówki żądań HTTP. W tym obiekcie jest rozróżniana wielkość liter. Zaleca się zamiast tego użycie request.getHeader('header-name') , co jest niewrażliwe na wielkość liter.
query Record<string, string> Klucze parametrów ciągu zapytania i wartości z adresu URL.
params Record<string, string> Kierowanie kluczy parametrów i wartości.
user HttpRequestUser | null Obiekt reprezentujący zalogowanego użytkownika za pośrednictwem uwierzytelniania usługi Functions, uwierzytelniania SWA lub wartości null, gdy taki użytkownik nie jest zalogowany.
body Buffer | string | any Jeśli typ nośnika to "application/octet-stream" lub "multipart/*", body jest buforem. Jeśli wartość jest ciągiem analizowany w formacie JSON, body jest analizowany obiekt. body W przeciwnym razie jest ciągiem.
rawBody string Treść jako ciąg. Pomimo nazwy ta właściwość nie zwraca buforu.
bufferBody Buffer Treść jako bufor.

Dostęp do żądania można uzyskać jako pierwszy argument procedury obsługi dla funkcji wyzwalanej przez protokół HTTP.

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

Obiekt HttpRequest ma następujące właściwości:

Właściwość Type Opis
method string Metoda żądania HTTP używana do wywoływania tej funkcji.
url string Adres URL żądania.
headers Headers Nagłówki żądań HTTP.
query URLSearchParams Klucze parametrów ciągu zapytania i wartości z adresu URL.
params Record<string, string> Kierowanie kluczy parametrów i wartości.
user HttpRequestUser | null Obiekt reprezentujący zalogowanego użytkownika za pośrednictwem uwierzytelniania usługi Functions, uwierzytelniania SWA lub wartości null, gdy taki użytkownik nie jest zalogowany.
body ReadableStream | null Treść jako strumień czytelny.
bodyUsed boolean Wartość logiczna wskazująca, czy treść jest już odczytana.

Aby uzyskać dostęp do treści żądania lub odpowiedzi, można użyć następujących metod:

Metoda Zwracany typ
arrayBuffer() Promise<ArrayBuffer>
blob() Promise<Blob>
formData() Promise<FormData>
json() Promise<unknown>
text() Promise<string>

Uwaga

Funkcje ciała można uruchamiać tylko raz; kolejne wywołania zostaną rozwiązane z pustymi ciągami/tablicąBuffers.

Odpowiedź HTTP

Odpowiedź można ustawić na kilka sposobów:

  • context.res Ustaw właściwość:

    module.exports = async function (context, request) {
        context.res = { body: `Hello, world!` };
    
  • Zwróć odpowiedź: Jeśli funkcja jest asynchronizna i ustawisz nazwę powiązania na $return w function.jsonpliku , możesz zwrócić odpowiedź bezpośrednio zamiast ustawiać ją na .context

    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
    
    module.exports = async function (context, request) {
        return { body: `Hello, world!` };
    
  • Ustaw nazwane powiązanie danych wyjściowych: ta opcja działa tak samo jak dowolne powiązanie inne niż HTTP. Nazwa powiązania w function.json pliku musi być zgodna z kluczem w context.bindingspliku lub "response1" w poniższym przykładzie:

    {
        "type": "http",
        "direction": "out",
        "name": "response1"
    }
    
    module.exports = async function (context, request) {
        context.bindings.response1 = { body: `Hello, world!` };
    
  • Wywołaj metodę context.res.send(): ta opcja jest przestarzała. Niejawnie wywołuje context.done() metodę i nie można jej używać w funkcji asynchronicznych.

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

Jeśli podczas ustawiania odpowiedzi zostanie utworzony nowy obiekt, ten obiekt musi być zgodny z interfejsem HttpResponseSimple , który ma następujące właściwości:

Właściwość Type Opis
headers Record<string, string> (opcjonalny) Nagłówki odpowiedzi HTTP.
cookies Cookie[] (opcjonalny) Pliki cookie odpowiedzi HTTP.
body any (opcjonalny) Treść odpowiedzi HTTP.
statusCode number (opcjonalny) Kod stanu odpowiedzi HTTP. Jeśli nie zostanie ustawiona, wartość domyślna to 200.
status number (opcjonalny) To samo co statusCode. Ta właściwość jest ignorowana, jeśli statusCode jest ustawiona.

Można również zmodyfikować context.res obiekt bez zastępowania go. Obiekt domyślny context.res używa interfejsu HttpResponseFull , który obsługuje następujące metody oprócz HttpResponseSimple właściwości:

Metoda opis
status() Ustawia stan.
setHeader() Ustawia pole nagłówka. UWAGA: res.set() i res.header() są również obsługiwane i robią to samo.
getHeader() Pobierz pole nagłówka. UWAGA: res.get() jest również obsługiwana i robi to samo.
removeHeader() Usuwa nagłówek.
type() Ustawia nagłówek "content-type".
send() Ta metoda jest przestarzała. Ustawia treść i wywołania context.done() , aby wskazać, że funkcja synchronizacji została zakończona. UWAGA: res.end() jest również obsługiwana i robi to samo.
sendStatus() Ta metoda jest przestarzała. Ustawia kod stanu i wywołania context.done() , aby wskazać, że funkcja synchronizacji została zakończona.
json() Ta metoda jest przestarzała. Ustawia wartość "content-type" na "application/json", ustawia treść i wywołuje context.done() polecenie, aby wskazać, że funkcja synchronizacji została zakończona.

Odpowiedź można ustawić na kilka sposobów:

  • Jako prosty interfejs z typem HttpResponseInit: Ta opcja jest najbardziej zwięzłym sposobem zwracania odpowiedzi.

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

    Interfejs HttpResponseInit ma następujące właściwości:

    Właściwość Type Opis
    body BodyInit (opcjonalny) Treść odpowiedzi HTTP jako jedna z ArrayBuffer, AsyncIterable<Uint8Array>, BlobNodeJS.ArrayBufferViewIterable<Uint8Array>URLSearchParamsFormData, , nulllub .string
    jsonBody any (opcjonalny) Treść odpowiedzi HTTP z możliwością serializacji JSON. W przypadku ustawienia HttpResponseInit.body właściwość jest ignorowana na rzecz tej właściwości.
    status number (opcjonalny) Kod stanu odpowiedzi HTTP. Jeśli nie zostanie ustawiona, wartość domyślna to 200.
    headers HeadersInit (opcjonalny) Nagłówki odpowiedzi HTTP.
    cookies Cookie[] (opcjonalny) Pliki cookie odpowiedzi HTTP.
  • Jako klasa z typem HttpResponse: Ta opcja zapewnia metody pomocnicze do odczytywania i modyfikowania różnych części odpowiedzi, takich jak nagłówki.

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

    Klasa HttpResponse akceptuje opcjonalny HttpResponseInit argument konstruktora i ma następujące właściwości:

    Właściwość Type Opis
    status number Kod stanu odpowiedzi HTTP.
    headers Headers Nagłówki odpowiedzi HTTP.
    cookies Cookie[] Pliki cookie odpowiedzi HTTP.
    body ReadableStream | null Treść jako strumień czytelny.
    bodyUsed boolean Wartość logiczna wskazująca, czy treść została już odczytana.

Strumienie HTTP (wersja zapoznawcza)

Strumienie HTTP to funkcja, która ułatwia przetwarzanie dużych danych, przesyłanie strumieniowe odpowiedzi openAI, dostarczanie zawartości dynamicznej i obsługę innych podstawowych scenariuszy HTTP. Umożliwia przesyłanie strumieniowe żądań do i odpowiedzi z punktów końcowych HTTP w aplikacji funkcji Node.js. Używaj strumieni HTTP w scenariuszach, w których aplikacja wymaga wymiany w czasie rzeczywistym i interakcji między klientem a serwerem za pośrednictwem protokołu HTTP. Możesz również użyć strumieni HTTP, aby uzyskać najlepszą wydajność i niezawodność aplikacji podczas korzystania z protokołu HTTP.

Strumienie HTTP są obecnie dostępne w wersji zapoznawczej.

Ważne

Strumienie HTTP nie są obsługiwane w modelu w wersji 3. Uaktualnij model do wersji 4, aby użyć funkcji przesyłania strumieniowego HTTP.

Istniejące HttpRequest typy i HttpResponse w modelu programowania w wersji 4 obsługują już różne sposoby obsługi treści komunikatów, w tym jako strumień.

Wymagania wstępne

Włączanie strumieni

Wykonaj następujące kroki, aby włączyć strumienie HTTP w aplikacji funkcji na platformie Azure i w projektach lokalnych:

  1. Jeśli planujesz przesyłanie strumieniowe dużych ilości danych, zmodyfikuj FUNCTIONS_REQUEST_BODY_SIZE_LIMIT ustawienie na platformie Azure. Domyślny maksymalny dozwolony rozmiar treści to 104857600, który ogranicza żądania do rozmiaru ok. 100 MB.

  2. W przypadku programowania lokalnego dodaj FUNCTIONS_REQUEST_BODY_SIZE_LIMIT również plik local.settings.json.

  3. Dodaj następujący kod do aplikacji w dowolnym pliku dołączonym przez pole główne.

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

Przykłady strumieni

W tym przykładzie pokazano funkcję wyzwalaną przez protokół HTTP, która odbiera dane za pośrednictwem żądania HTTP POST, a funkcja przesyła strumieniowo te dane do określonego pliku wyjściowego:

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

W tym przykładzie pokazano funkcję wyzwalaną przez protokół HTTP, która przesyła strumieniowo zawartość pliku jako odpowiedź na przychodzące żądania HTTP GET:

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

Zagadnienia dotyczące strumienia

  • Obiekt request.params nie jest obsługiwany w przypadku korzystania ze strumieni HTTP w trakcie korzystania z wersji zapoznawczej. Aby uzyskać więcej informacji i sugerowanych obejść, zapoznaj się z tym problemem z usługą GitHub.

  • Użyj request.body polecenia , aby uzyskać maksymalną korzyść z używania strumieni. Nadal możesz nadal używać metod takich jak request.text(), które zawsze zwracają treść jako ciąg.

Punkty zaczepienia

Punkty zaczepienia nie są obsługiwane w modelu w wersji 3. Uaktualnij model do wersji 4, aby użyć punktów zaczepienia.

Użyj punktu zaczepienia, aby wykonać kod w różnych punktach cyklu życia usługi Azure Functions. Haki są wykonywane w kolejności ich rejestracji i można je zarejestrować z dowolnego pliku w aplikacji. Obecnie istnieją dwa zakresy punktów zaczepienia, poziom "aplikacja" i poziom "wywołania".

Wcięcie wywołania

Wywołania zaczepienia są wykonywane raz na wywołanie funkcji, albo przed w haku preInvocation lub po w haku postInvocation . Domyślnie punkt zaczepienia jest wykonywany dla wszystkich typów wyzwalaczy, ale można również filtrować według typu. W poniższym przykładzie pokazano, jak zarejestrować punkt zaczepienia wywołania i filtrować według typu wyzwalacza:

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

Pierwszym argumentem programu obsługi punktów zaczepienia jest obiekt kontekstu specyficzny dla tego typu haka.

Obiekt PreInvocationContext ma następujące właściwości:

Właściwości opis
inputs Argumenty przekazane do wywołania.
functionHandler Procedura obsługi funkcji dla wywołania. Zmiany tej wartości wpływają na samą funkcję.
invocationContext Obiekt kontekstu wywołania przekazany do funkcji.
hookData Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia.

Obiekt PostInvocationContext ma następujące właściwości:

Właściwości opis
inputs Argumenty przekazane do wywołania.
result Wynik funkcji. Zmiany tej wartości wpływają na ogólny wynik funkcji.
error Błąd zgłaszany przez funkcję lub wartość null/niezdefiniowany, jeśli nie ma błędu. Zmiany tej wartości wpływają na ogólny wynik funkcji.
invocationContext Obiekt kontekstu wywołania przekazany do funkcji.
hookData Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia.

Podpięcie aplikacji

Elementy zaczepienia aplikacji są wykonywane raz na wystąpienie aplikacji podczas uruchamiania w appStart haczyku lub podczas kończenia działania w haku appTerminate . Kończenie działania aplikacji ma ograniczony czas do wykonania i nie jest wykonywane we wszystkich scenariuszach.

Środowisko uruchomieniowe usługi Azure Functions obecnie nie obsługuje rejestrowania kontekstu poza wywołaniem. Użyj pakietu npm aplikacji Szczegółowe informacje, aby rejestrować dane podczas punktów zaczepienia na poziomie aplikacji.

W poniższym przykładzie rejestruje się punkt zaczepienia aplikacji:

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

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

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

Pierwszym argumentem programu obsługi punktów zaczepienia jest obiekt kontekstu specyficzny dla tego typu haka.

Obiekt AppStartContext ma następujące właściwości:

Właściwości opis
hookData Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia.

Obiekt AppTerminateContext ma następujące właściwości:

Właściwości opis
hookData Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia.

Skalowanie i współbieżność

Domyślnie usługa Azure Functions automatycznie monitoruje obciążenie aplikacji i tworzy więcej wystąpień hosta dla Node.js zgodnie z potrzebami. Usługa Azure Functions używa wbudowanych (nie konfigurowalnych przez użytkownika) progów dla różnych typów wyzwalaczy, aby zdecydować, kiedy dodać wystąpienia, takie jak wiek komunikatów i rozmiar kolejki dla klasy QueueTrigger. Aby uzyskać więcej informacji, zobacz Jak działają plany Zużycie i Premium.

To zachowanie skalowania jest wystarczające dla wielu aplikacji Node.js. W przypadku aplikacji powiązanych z procesorem CPU można dodatkowo zwiększyć wydajność przy użyciu wielu procesów roboczych języka. Można zwiększyć liczbę procesów roboczych na hosta z wartości domyślnej 1 do maksymalnie 10, używając ustawienia aplikacji FUNCTIONS_WORKER_PROCESS_COUNT . Następnie usługa Azure Functions próbuje równomiernie dystrybuować równoczesne wywołania funkcji między tymi procesami roboczymi. To zachowanie sprawia, że mniej prawdopodobne jest, że funkcja intensywnie korzystająca z procesora CPU blokuje działanie innych funkcji. Ustawienie dotyczy każdego hosta tworzonego przez usługę Azure Functions podczas skalowania aplikacji w celu spełnienia wymagań.

Ostrzeżenie

FUNCTIONS_WORKER_PROCESS_COUNT Użyj ustawienia z ostrożnością. Wiele procesów uruchomionych w tym samym wystąpieniu może prowadzić do nieprzewidywalnego zachowania i zwiększyć czas ładowania funkcji. Jeśli używasz tego ustawienia, zdecydowanie zaleca się przesunięcie tych wad przez uruchomienie z pliku pakietu.

Wersja środowiska Node

Możesz zobaczyć bieżącą wersję używaną przez środowisko uruchomieniowe, logując się process.version z dowolnej funkcji. Zobacz supported versions listę wersji Node.js obsługiwanych przez poszczególne modele programowania.

Ustawianie wersji środowiska Node

Sposób uaktualniania wersji Node.js zależy od systemu operacyjnego, na którym działa aplikacja funkcji.

W przypadku uruchamiania w systemie Windows Node.js wersja jest ustawiana przez WEBSITE_NODE_DEFAULT_VERSION ustawienie aplikacji. To ustawienie można zaktualizować przy użyciu interfejsu wiersza polecenia platformy Azure lub w witrynie Azure Portal.

Aby uzyskać więcej informacji na temat wersji Node.js, zobacz Obsługiwane wersje.

Przed uaktualnieniem Node.js wersji upewnij się, że aplikacja funkcji jest uruchomiona w najnowszej wersji środowiska uruchomieniowego usługi Azure Functions. Jeśli musisz uaktualnić wersję środowiska uruchomieniowego, zobacz Migrowanie aplikacji z usługi Azure Functions w wersji 3.x do wersji 4.x.

Uruchom polecenie interfejsu wiersza polecenia az functionapp config appsettings set platformy Azure, aby zaktualizować wersję Node.js dla aplikacji funkcji uruchomionej w systemie Windows:

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

Spowoduje to ustawienie WEBSITE_NODE_DEFAULT_VERSION aplikacji dla obsługiwanej wersji LTS programu ~20.

Po wprowadzeniu zmian aplikacja funkcji zostanie ponownie uruchomiona. Aby dowiedzieć się więcej o obsłudze usługi Functions dla Node.js, zobacz Zasady obsługi środowiska uruchomieniowego języka.

Zmienne środowiskowe

Zmienne środowiskowe mogą być przydatne w przypadku wpisów tajnych operacyjnych (parametry połączenia, kluczy, punktów końcowych itp.) lub ustawień środowiskowych, takich jak zmienne profilowania. Zmienne środowiskowe można dodawać zarówno w środowiskach lokalnych, jak i w chmurze, i uzyskiwać do nich dostęp za pomocą process.env kodu funkcji.

Poniższy przykład rejestruje zmienną środowiskową WEBSITE_SITE_NAME :

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

W lokalnym środowisku projektowym

Po uruchomieniu lokalnie projekt funkcji zawiera local.settings.json plik, w którym są przechowywane zmienne środowiskowe w Values obiekcie.

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

W środowisku chmury platformy Azure

Po uruchomieniu na platformie Azure aplikacja funkcji umożliwia ustawianie i używanie ustawień aplikacji, takich jak parametry połączenia usługi, i uwidacznia te ustawienia jako zmienne środowiskowe podczas wykonywania.

Istnieje kilka sposobów dodawania, aktualizowania i usuwania ustawień aplikacji funkcji:

Zmiany ustawień aplikacji funkcji wymagają ponownego uruchomienia aplikacji funkcji.

Zmienne środowiskowe procesu roboczego

Istnieje kilka zmiennych środowiskowych funkcji specyficznych dla Node.js:

languageWorkers__node__arguments

To ustawienie umożliwia określenie niestandardowych argumentów podczas uruchamiania procesu Node.js. Jest ona najczęściej używana lokalnie do uruchamiania procesu roboczego w trybie debugowania, ale może być również używana na platformie Azure, jeśli potrzebujesz argumentów niestandardowych.

Ostrzeżenie

Jeśli to możliwe, unikaj korzystania z languageWorkers__node__arguments platformy Azure, ponieważ może to mieć negatywny wpływ na zimne czasy rozpoczęcia. Zamiast używać wstępnie rozgrzanych procesów roboczych, środowisko uruchomieniowe musi od podstaw uruchomić nowy proces roboczy z niestandardowymi argumentami.

logging__logLevel__Worker

To ustawienie dostosowuje domyślny poziom dziennika dla dzienników procesów roboczych specyficznych dla Node.js. Domyślnie wyświetlane są tylko dzienniki ostrzegawcze lub dzienniki błędów, ale można je ustawić na information lub debug ułatwić diagnozowanie problemów z Node.js procesem roboczym. Aby uzyskać więcej informacji, zobacz Konfigurowanie poziomów dziennika.

Moduły ECMAScript (wersja zapoznawcza)

Uwaga

Ponieważ moduły ECMAScript są obecnie funkcją w wersji zapoznawczej w Node.js 14 lub nowszym w usłudze Azure Functions.

Moduły ECMAScript (moduły ES) to nowy oficjalny standardowy system modułów dla Node.js. Do tej pory przykłady kodu w tym artykule używają składni CommonJS. W przypadku uruchamiania usługi Azure Functions w wersji Node.js 14 lub nowszej można zapisać funkcje przy użyciu składni modułów ES.

Aby użyć modułów ES w funkcji, zmień jego nazwę pliku, aby użyć .mjs rozszerzenia. Poniższy przykład pliku index.mjs to funkcja wyzwalana przez protokół HTTP, która używa składni modułów ES do importowania uuid biblioteki i zwracania wartości.

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

Konfigurowanie punktu wejścia funkcji

Właściwości function.jsonscriptFile i entryPoint mogą służyć do konfigurowania lokalizacji i nazwy wyeksportowanej funkcji. Właściwość jest wymagana scriptFile , gdy używasz języka TypeScript i powinna wskazywać skompilowany kod JavaScript.

Korzystanie z akcji scriptFile

Domyślnie funkcja JavaScript jest wykonywana z index.jspliku , który współudzieli ten sam katalog nadrzędny co odpowiadający mu function.jsonelement .

scriptFile Może służyć do pobierania struktury folderów, która wygląda jak w poniższym przykładzie:

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

Element function.json for myFirstFunction powinien zawierać właściwość wskazującą scriptFile plik z wyeksportowaną funkcją do uruchomienia.

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

Korzystanie z akcji entryPoint

W modelu w wersji 3 należy wyeksportować funkcję przy użyciu polecenia module.exports w celu znalezienia i uruchomienia. Domyślnie funkcja wykonywana po wyzwoleniu jest jedynym eksportem z tego pliku, eksportem o nazwie lub eksportem o nazwie runindex. W poniższym przykładzie ustawiono entryPointfunction.json wartość niestandardową "logHello":

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

module.exports = { logHello };

Debugowanie lokalne

Zaleca się używanie programu VS Code do debugowania lokalnego, co powoduje automatyczne uruchomienie procesu Node.js w trybie debugowania i dołączenie go do procesu. Aby uzyskać więcej informacji, zobacz uruchamianie funkcji lokalnie.

Jeśli używasz innego narzędzia do debugowania lub chcesz ręcznie uruchomić proces Node.js w trybie debugowania, dodaj "languageWorkers__node__arguments": "--inspect" element Values w local.settings.json. Argument --inspect informuje Node.js domyślnie nasłuchiwać klienta debugowania na porcie 9229. Aby uzyskać więcej informacji, zobacz przewodnik debugowania Node.js.

Zalecenia

W tej sekcji opisano kilka wzorców wpływających na Node.js aplikacji, które zalecamy.

Wybieranie planów usługi App Service z jednym procesorem wirtualnym

Podczas tworzenia aplikacji funkcji korzystającej z planu usługi App Service zalecamy wybranie planu pojedynczego procesora wirtualnego zamiast planu z wieloma procesorami wirtualnymi. Obecnie funkcje Node.js działają wydajniej na maszynach wirtualnych z jedną procesorem wirtualnym, a użycie większych maszyn wirtualnych nie generuje oczekiwanych ulepszeń wydajności. W razie potrzeby możesz ręcznie skalować w poziomie, dodając więcej wystąpień maszyn wirtualnych z pojedynczą procesorem wirtualnym lub możesz włączyć skalowanie automatyczne. Aby uzyskać więcej informacji, zobacz Ręczne lub automatyczne skalowanie liczby wystąpień.

Uruchamianie z pliku pakietu

Podczas opracowywania usługi Azure Functions w modelu hostingu bezserwerowego zimne starty są rzeczywistością. Zimny start odnosi się do pierwszego uruchomienia aplikacji funkcji po okresie braku aktywności, co trwa dłużej. W przypadku Node.js aplikacji z dużymi drzewami zależności w szczególności zimny start może być znaczący. Aby przyspieszyć proces zimnego uruchamiania, uruchom funkcje jako plik pakietu, jeśli to możliwe. Wiele metod wdrażania używa tego modelu domyślnie, ale jeśli występują duże zimne uruchomienia, sprawdź, czy działasz w ten sposób.

Używanie pojedynczego klienta statycznego

Jeśli używasz klienta specyficznego dla usługi w aplikacji usługi Azure Functions, nie twórz nowego klienta z każdym wywołaniem funkcji, ponieważ można osiągnąć limity połączeń. Zamiast tego utwórz jednego, statycznego klienta w zakresie globalnym. Aby uzyskać więcej informacji, zobacz Zarządzanie połączeniami w usłudze Azure Functions.

Używanie i asyncawait

Podczas pisania usługi Azure Functions w Node.js należy napisać kod przy użyciu async słów kluczowych i await . Pisanie kodu przy użyciu funkcji async i await zamiast wywołań zwrotnych lub .then i .catch z narzędziem Promises pomaga uniknąć dwóch typowych problemów:

  • Zgłaszanie nieuchwyconych wyjątków, które powodują awarię procesu Node.js, potencjalnie wpływające na wykonywanie innych funkcji.
  • Nieoczekiwane zachowanie, takie jak brakujące dzienniki z context.logprogramu , spowodowane przez wywołania asynchroniczne, które nie są prawidłowo oczekiwane.

W poniższym przykładzie metoda fs.readFile asynchroniczna jest wywoływana z funkcją wywołania zwrotnego pierwszego błędu jako jej drugi parametr. Ten kod powoduje, że oba wymienione wcześniej problemy. Wyjątek, który nie jest jawnie przechwycony w prawidłowym zakresie, może ulec awarii całego procesu (problem nr 1). Zwracanie bez zapewnienia zakończenia wywołania zwrotnego oznacza, że odpowiedź HTTP czasami będzie mieć pustą treść (problem nr 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 };
    },
});

W poniższym przykładzie metoda fs.readFile asynchroniczna jest wywoływana z funkcją wywołania zwrotnego pierwszego błędu jako jej drugi parametr. Ten kod powoduje, że oba wymienione wcześniej problemy. Wyjątek, który nie jest jawnie przechwycony w prawidłowym zakresie, może ulec awarii całego procesu (problem nr 1). Wywołanie przestarzałej context.done() metody poza zakresem wywołania zwrotnego może sygnalizować zakończenie działania funkcji przed odczytaniem pliku (problem nr 2). W tym przykładzie wywołanie context.done() zbyt wcześnie powoduje brakujących wpisów dziennika rozpoczynających się od 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();
}

async Użyj słów kluczowych iawait, aby uniknąć obu tych problemów. Większość interfejsów API w ekosystemie Node.js została przekonwertowana na obsługę obietnic w jakiejś formie. Na przykład, począwszy od wersji 14, Node.js udostępnia fs/promises interfejs API do zastąpienia interfejsu fs API wywołania zwrotnego.

W poniższym przykładzie wszelkie nieobsługiwane wyjątki zgłoszone podczas wykonywania funkcji kończą się niepowodzeniem tylko pojedynczego wywołania, które zgłosiło wyjątek. Słowo await kluczowe oznacza, że kroki wykonywane readFile tylko po jego zakończeniu.

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

W systemach async i awaitnie trzeba również wywoływać wywołania zwrotnego context.done() .

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

Rozwiązywanie problemów

Zobacz przewodnik rozwiązywania problemów z Node.js.

Następne kroki

Aby uzyskać więcej informacji, zobacz następujące zasoby: