Azure Functions Node.js開發人員指南

本指南是使用 JavaScript 或 TypeScript 開發 Azure Functions 的簡介。 本文假設您已閱讀 Azure Functions 開發人員指南

重要

本文的內容會根據您選擇的Node.js程序設計模型,在此頁面頂端的選取器中變更。 您選擇的版本應該符合您在應用程式中所使用的 npm 套件版本 @azure/functions 。 如果您未列出 package.json該套件,則預設值為 v3。 深入瞭解移轉指南中的 v3 和 v4 之間的差異。

身為Node.js開發人員,您可能也對下列其中一篇文章感興趣:

開始使用 概念 引導式學習

考量

  • Node.js程序設計模型不應與 Azure Functions 運行時間混淆:
    • 程序設計模型:定義您撰寫程序代碼的方式,以及 JavaScript 和 TypeScript 的特定方式。
    • 運行時間:定義 Azure Functions 的基礎行為,並跨所有語言共用。
  • 程序設計模型的版本會嚴格系結至 npm 套件的版本 @azure/functions 。 其版本與運行時間無關。 運行時間和程式設計模型都會使用數位 4 作為其最新的主要版本,但這是巧合。
  • 您無法在相同的函式應用程式中混合 v3 和 v4 程式設計模型。 一旦您在應用程式中註冊一個 v4 函式,就會忽略function.json檔案中註冊的任何 v3 函式。

支援的版本

下表顯示Node.js程序設計模型的每個版本,以及其支援的 Azure Functions 運行時間和Node.js版本。

程序設計模型版本 支援層級 Functions 運行時間版本 Node.js 版本 描述
4.x GA 4.25+ 20.x、18.x 支援彈性的檔案結構和以程式代碼為中心的觸發程式和系結方法。
3.x GA 4.x 20.x、18.x、16.x、14.x 需要具有觸發程式和系結在 「function.json」檔案中宣告的特定檔案結構
2.x n/a 3.x 14.x、12.x、10.x 已於 2022 年 12 月 13 日終止支援。 如需詳細資訊,請參閱 函式版本
1.x n/a 2.x 10.x、8.x 已於 2022 年 12 月 13 日終止支援。 如需詳細資訊,請參閱 函式版本

資料夾結構

JavaScript 專案所需的資料夾結構看起來像下列範例:

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

主要項目資料夾 <project_root>可以包含下列檔案:

  • .vscode/: (選擇性) 包含預存的 Visual Studio Code 組態。 若要深入瞭解,請參閱 Visual StudioCode設定
  • myFirstFunction/function.json:包含函式觸發程式、輸入和輸出的組態。 目錄的名稱會決定函式的名稱。
  • myFirstFunction/index.js:儲存函式程序代碼。 若要變更此預設檔案路徑,請參閱 使用 scriptFile
  • .funcignore:(選擇性) 宣告不應該發佈至 Azure 的檔案。 通常,此檔案包含 .vscode/ 來忽略您的編輯器設定、 測試/ 忽略測試案例,以及 local.settings.json 以防止發佈本機應用程式設定。
  • host.json:包含會影響函式應用程式實例中所有函式的組態選項。 此檔案會發佈至 Azure。 並非所有選項都支援在本機執行。 若要深入瞭解,請參閱 host.json
  • local.settings.json:用來在本機執行應用程式設定和 連接字串。 此檔案不會發佈至 Azure。 若要深入瞭解,請參閱 local.settings.file
  • package.json:包含組態選項,例如套件相依性清單、主要進入點和腳本。

JavaScript 專案的建議資料夾結構看起來像下列範例:

<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

主要項目資料夾 <project_root>可以包含下列檔案:

  • .vscode/: (選擇性) 包含預存的 Visual Studio Code 組態。 若要深入瞭解,請參閱 Visual StudioCode設定
  • src/functions/:所有函式及其相關觸發程式和系結的預設位置。
  • test/:(選擇性) 包含函式應用程式的測試案例。
  • .funcignore:(選擇性) 宣告不應該發佈至 Azure 的檔案。 通常,此檔案包含 .vscode/ 來忽略您的編輯器設定、 測試/ 忽略測試案例,以及 local.settings.json 以防止發佈本機應用程式設定。
  • host.json:包含會影響函式應用程式實例中所有函式的組態選項。 此檔案會發佈至 Azure。 並非所有選項都支援在本機執行。 若要深入瞭解,請參閱 host.json
  • local.settings.json:用來在本機執行時儲存應用程式設定和 連接字串。 此檔案不會發佈至 Azure。 若要深入瞭解,請參閱 local.settings.file
  • package.json:包含組態選項,例如套件相依性清單、主要進入點和腳本。

註冊函式

v3 模型會根據兩個檔案的存在來註冊函式。 首先,您需要一個 function.json 位於應用程式根目錄下一層資料夾的檔案。 其次,您需要可匯出函式的 JavaScript 檔案。 根據預設,模型會在與 function.json相同的資料夾中尋找index.js檔案。 如果您使用 TypeScript,則必須使用 scriptFile 中的 function.json 屬性來指向已編譯的 JavaScript 檔案。 若要自定義函式的檔案位置或匯出名稱,請參閱 設定函式的進入點

您匯出的函式應該一律在 v3 模型中宣告為 async function 。 您可以匯出同步函式,但您必須呼叫 context.done() 來表示函式已完成,但不建議這麼做。

您的函式會傳遞調用context做為第一個自變數,而您的輸入會作為其餘自變數。

下列範例是一個簡單的函式,會記錄其已觸發並使用 回應 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!' };
};

程序設計模型會根據 main 中的 package.json欄位載入函式。 您可以使用 glob 模式,將main字段設定為單一檔案或多個檔案。 下表顯示 欄位的 main 範例值:

範例 描述
src/index.js 從單一根檔案註冊函式。
src/functions/*.js 從自己的檔案註冊每個函式。
src/{index.js,functions/*.js} 組合可讓您從自己的檔案註冊每個函式,但仍有一般應用層級程式代碼的根檔案。

若要註冊函式,您必須從 @azure/functions npm 模組匯app入 物件,並呼叫觸發程式類型特有的方法。 註冊函式時的第一個自變數是函式名稱。 第二個自變數是物件 options ,指定觸發程式、處理程式和任何其他輸入或輸出的組態。 在某些情況下,不需要觸發程式組態,您可以將處理程式直接傳遞為第二個 options 自變數,而不是物件。

只要根據檔案package.json中的欄位載入該檔案,main即可從專案中的任何檔案註冊函式。 函式應該在全域範圍註冊,因為一旦開始執行,就無法註冊函式。

下列範例是一個簡單的函式,會記錄其已觸發並使用 回應 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!' };
    }
});

Inputs and outputs

您的函式必須有一個稱為觸發程式的主要輸入。 它也可能有次要輸入和/或輸出。 輸入和輸出是在檔案 function.json 中設定,也稱為 結。

輸入

輸入是系結,且 direction 設定為 in。 觸發程式和次要輸入之間的主要差異在於 type ,觸發程式的 結尾 Trigger為 ,例如類型 blobTrigger 與類型 blob。 大部分的函式只會使用觸發程式,而且不支援許多次要輸入類型。

您可以透過數種方式存取輸入:

  • [建議] 當做傳遞至函式的自變數: 以與 中 function.json定義的自變數相同順序使用自變數。 namefunction.json定義的 屬性不需要符合自變數的名稱,不過為了組織而建議使用。

    module.exports = async function (context, myTrigger, myInput, myOtherInput) { ... };
    
  • 做為的屬性 context.bindings 使用索引鍵比 name 對 中 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);
    };
    

輸出

輸出是具有 direction 設定為 out 的系結,而且可以透過數種方式來設定:

  • [建議用於單一輸出] 直接傳回值: 如果您使用異步函式,您可以直接傳回值。 您必須將輸出系結的 屬性變更 name$returnfunction.json 如下列範例所示:

    {
        "name": "$return",
        "type": "http",
        "direction": "out"
    }
    
    module.exports = async function (context, request) {
        return {
            body: "Hello, world!"
        };
    }
    
  • [建議用於多個輸出] 傳回包含所有輸出的物件: 如果您使用異步函式,可以傳回屬性符合 您 function.json中每個系結名稱的物件。 下列範例使用名為 “HTTPResponse” 和 “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
        };
    };
    
  • 在 上 context.bindings設定值: 如果您不是使用異步函式,或不想使用上述選項,您可以直接在 上 context.bindings設定值,其中索引鍵符合系結的名稱。 下列範例使用名為 “HTTPResponse” 和 “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;
    };
    

系結數據類型

您可以在 dataType 輸入系結上使用 屬性來變更輸入的類型,但有一些限制:

  • 在Node.js中,僅 string 支援 和 binarystream 不是)
  • 若為 HTTP 輸入, dataType 則會忽略 屬性。 請改用 物件上的 request 屬性,以您想要的格式取得本文。 如需詳細資訊,請參閱 HTTP 要求

在下列記憶體佇列觸發程式的範例中,的默認類型myQueueItem是 ,但如果您將 設定dataTypebinary,則類型會變更為 Node.js Bufferstring

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

您的函式必須有一個稱為觸發程式的主要輸入。 它也可能有次要輸入、稱為傳回輸出的主要輸出和/或次要輸出。 輸入和輸出也稱為 Node.js程序設計模型內容之外的系結 。 在模型的 v4 之前,這些系結是在檔案中 function.json 設定的。

觸發程式輸入

觸發程式是唯一必要的輸入或輸出。 針對大部分的觸發程式類型,您會在以觸發程式類型命名的物件 app 上使用 方法註冊函式。 您可以直接在 自變數上指定觸發程式特定的組 options 態。 例如,HTTP 觸發程式可讓您指定路由。 在執行期間,對應至此觸發程式的值會當做處理程式的第一個自變數傳入。

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

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

傳回輸出

傳回輸出是選擇性的,在某些情況下預設會設定。 例如,向 註冊的 app.http HTTP 觸發程式已設定為自動傳回 HTTP 回應輸出。 針對大部分的輸出類型,您會在自變數上options指定傳回組態,並透過從@azure/functions模組匯出的物件來指定 output 。 在執行期間,您會從處理程式傳回它來設定此輸出。

下列範例使用定時器觸發程式和記憶體佇列輸出

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

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

額外的輸入和輸出

除了觸發程式和傳回之外,您可以在註冊函式時指定自變數的額外 options 輸入或輸出。 input從模組導出的 @azure/functionsoutput 物件提供型別特定方法,以協助建構組態。 在執行期間,您會使用 或 context.extraOutputs.set取得或 設定值context.extraInputs.get,並傳入原始組態物件做為第一個自變數。

下列範例是由記憶體佇列所觸發的函式,其額外記憶體 Blob 輸入會複製到額外的記憶體 Blob 輸出。 佇列訊息應該是檔名,並以系結運算式的協助取代{queueTrigger}為要複製的 Blob 名稱。

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

一般輸入和輸出

模組app@azure/functions導出的、 triggerinput、 和 output 物件會為大多數類型提供特定型別的方法。 針對不支援的所有類型, generic 會提供方法來讓您手動指定組態。 generic如果您想要變更類型特定方法所提供的預設設定,也可以使用 方法。

下列範例是使用泛型方法而非類型特定方法的簡單 HTTP 觸發函式。

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

調用內容

函式的每個調用都會傳遞調用 context 物件,用來讀取輸入、設定輸出、寫入記錄,以及讀取各種元數據。 在 v3 模型中,內容物件一律是傳遞至處理程式的第一個自變數。

物件 context 具有下列屬性:

屬性 說明
invocationId 目前函式調用的標識碼。
executionContext 請參閱 執行內容
bindings 請參閱 系結
bindingData 此調用之觸發程式輸入的相關元數據,不包括值本身。 例如,事件中 樞觸發程式 具有 enqueuedTimeUtc 屬性。
traceContext 分散式追蹤的內容。 如需詳細資訊,請參閱Trace Context
bindingDefinitions 輸入和輸出的組態,如 中所 function.json定義。
req 請參閱 HTTP 要求
res 請參閱 HTTP 回應

context.executionContext

物件 context.executionContext 具有下列屬性:

屬性 說明
invocationId 目前函式調用的標識碼。
functionName 正在叫用之函式的名稱。 包含 function.json 檔案的資料夾名稱會決定函式的名稱。
functionDirectory 包含檔案的資料夾 function.json
retryContext 請參閱 重試內容

context.executionContext.retryContext

物件 context.executionContext.retryContext 具有下列屬性:

屬性 說明
retryCount 代表目前重試嘗試的數位。
maxRetryCount 重試執行的次數上限。 要無限期重試的 -1 值。
exception 導致重試的例外狀況。

context.bindings

對像是 context.bindings 用來讀取輸入或設定輸出。 下列範例是記憶體佇列觸發程式,其會使用 context.bindings 將記憶體 Blob 輸入複製到記憶體 Blob 輸出。 佇列訊息的內容會{queueTrigger}以系結表達式的協助取代為要複製的檔名。

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

方法 context.done 已被取代。 支援異步函式之前,您會透過呼叫 context.done()來發出函式的訊號:

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

現在,建議您移除 對 context.done() 的呼叫,並將函式標示為異步,使其傳回承諾(即使您沒有任何 await 專案)。 一旦函式完成(換句話說,傳回的承諾就會解決),v3 模型就會知道您的函式已完成。

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

函式的每個調用都會傳遞調用 context 物件,其中包含用於記錄的調用和方法的相關信息。 在 v4 模型中, context 物件通常是傳遞至處理程式的第二個自變數。

類別 InvocationContext 具有下列屬性:

屬性 說明
invocationId 目前函式調用的標識碼。
functionName 函數的名稱。
extraInputs 用來取得額外輸入的值。 如需詳細資訊,請參閱 額外的輸入和輸出
extraOutputs 用來設定額外輸出的值。 如需詳細資訊,請參閱 額外的輸入和輸出
retryContext 請參閱 重試內容
traceContext 分散式追蹤的內容。 如需詳細資訊,請參閱Trace Context
triggerMetadata 此調用之觸發程式輸入的相關元數據,不包括值本身。 例如,事件中 樞觸發程式 具有 enqueuedTimeUtc 屬性。
options 註冊函式時所使用的選項,在驗證函式之後,以及明確指定預設值。

重試內容

物件 retryContext 具有下列屬性:

屬性 說明
retryCount 代表目前重試嘗試的數位。
maxRetryCount 重試執行的次數上限。 要無限期重試的 -1 值。
exception 導致重試的例外狀況。

如需詳細資訊,請參閱retry-policies

記錄

在 Azure Functions 中,建議使用 context.log() 來寫入記錄。 Azure Functions 與 Azure 應用程式 Insights 整合,以更妥善地擷取函式應用程式記錄。 Application Insights 是 Azure 監視器的一部分,提供收集、可視化轉譯和分析應用程式記錄和追蹤輸出的設施。 若要深入瞭解,請參閱 監視 Azure Functions

注意

如果您使用替代Node.jsconsole.log方法,則會在應用層級追蹤這些記錄,且不會與任何特定函式產生關聯。 強烈建議您用於context記錄,console而不是讓所有記錄都與特定函式相關聯。

下列範例會在預設的「資訊」層級寫入記錄檔,包括叫用標識碼:

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

記錄層級

除了預設 context.log 方法之外,您還可以使用下列方法,讓您在特定層級寫入記錄:

方法 描述
context.log.error() 將錯誤層級事件寫入記錄。
context.log.warn() 將警告層級事件寫入記錄。
context.log.info() 將資訊層級事件寫入記錄。
context.log.verbose() 將追蹤層級事件寫入記錄。
方法 描述
context.trace() 將追蹤層級事件寫入記錄。
context.debug() 將偵錯層級事件寫入記錄。
context.info() 將資訊層級事件寫入記錄。
context.warn() 將警告層級事件寫入記錄。
context.error() 將錯誤層級事件寫入記錄。

設定記錄層級

Azure Functions 可讓您定義追蹤和檢視記錄時要使用的臨界值層級。 若要設定臨界值,請使用 logging.logLevel 檔案中的 host.json 屬性。 這個屬性可讓您定義套用至所有函式的預設層級,或每個個別函式的臨界值。 若要深入瞭解,請參閱 如何設定 Azure Functions 的監視。

追蹤自訂數據

根據預設,Azure Functions 會將輸出寫入 Application Insights 做為追蹤。 如需更多控制權,您可以改用 Application Insights Node.js SDK ,將自定義數據傳送至 Application Insights 實例。

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

參數會將 tagOverrides 設定 operation_Id 為函式的調用標識碼。 此設定可讓您將指定函式調用的所有自動產生和自定義記錄相互關聯。

HTTP 觸發程式

HTTP 和 Webhook 觸發程式會使用要求和響應物件來表示 HTTP 訊息。

HTTP 和 Webhook 觸發程式會使用 HttpRequestHttpResponse 物件來表示 HTTP 訊息。 類別代表提取標準的子集,使用Node.js的undici套件。

HTTP 要求

您可以透過數種方式存取要求:

  • 作為函式的第二個自變數:

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

    module.exports = async function (context, request) {
        context.log(`Http function processed request for url "${context.req.url}"`);
    
  • 從具名輸入系結: 此選項的運作方式與任何非 HTTP 系結相同。 中的 function.json 系結名稱必須符合 中的索引鍵 context.bindings,或下列範例中的 “request1” :

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

物件 HttpRequest 具有下列屬性:

屬性 類型​ 描述
method string 用來叫用此函式的 HTTP 要求方法。
url string 要求 URL。
headers Record<string, string> HTTP 要求標頭。 此物件區分大小寫。 建議改用 request.getHeader('header-name') ,這不區分大小寫。
query Record<string, string> 從 URL 查詢字串參數索引鍵和值。
params Record<string, string> 路由參數索引鍵和值。
user HttpRequestUser | null 代表已登入使用者的物件,無論是透過 Functions 驗證、SWA 驗證,或 Null,當沒有這類使用者登入時。
body Buffer | string | any 如果媒體類型是 「application/octet-stream」 或 「multipart/*」, body 則為 Buffer。 如果值為 JSON 剖析的字串, body 則 為已剖析的物件。 否則為 body 字串。
rawBody string 本文做為字串。 儘管有名稱,但此屬性不會傳回 Buffer。
bufferBody Buffer 本文做為緩衝區。

要求可以做為 HTTP 觸發函式處理程式的第一個自變數來存取。

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

物件 HttpRequest 具有下列屬性:

屬性 類型​ 描述
method string 用來叫用此函式的 HTTP 要求方法。
url string 要求 URL。
headers Headers HTTP 要求標頭。
query URLSearchParams 從 URL 查詢字串參數索引鍵和值。
params Record<string, string> 路由參數索引鍵和值。
user HttpRequestUser | null 代表已登入使用者的物件,無論是透過 Functions 驗證、SWA 驗證,或 Null,當沒有這類使用者登入時。
body ReadableStream | null 主體為可讀取數據流。
bodyUsed boolean 布爾值,指出本文是否已讀取。

若要存取要求或響應的主體,可以使用下列方法:

方法 傳回類型
arrayBuffer() Promise<ArrayBuffer>
blob() Promise<Blob>
formData() Promise<FormData>
json() Promise<unknown>
text() Promise<string>

注意

主體函式只能執行一次;後續呼叫將會使用空字串/ArrayBuffers 解析。

HTTP 回應

回應可以透過數種方式來設定:

  • context.res設定 屬性:

    module.exports = async function (context, request) {
        context.res = { body: `Hello, world!` };
    
  • 傳回回應:如果您的函式是異步的,而且您在 中function.json將系結名稱設定為 $return ,您可以直接傳回回應,而不是在 上設定context它。

    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
    
    module.exports = async function (context, request) {
        return { body: `Hello, world!` };
    
  • 設定具名輸出系結: 此選項的運作方式與任何非 HTTP 系結相同。 中的 function.json 系結名稱必須符合 中的索引鍵 context.bindings,或下列範例中的 “response1” :

    {
        "type": "http",
        "direction": "out",
        "name": "response1"
    }
    
    module.exports = async function (context, request) {
        context.bindings.response1 = { body: `Hello, world!` };
    
  • 呼叫 context.res.send() 此選項已被取代。 它會隱含地呼叫 context.done() ,且無法在異步函式中使用。

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

如果您在設定回應時建立新的物件,該物件必須符合 HttpResponseSimple 具有下列屬性的介面:

屬性 類型​ 描述
headers Record<string, string> (選用) HTTP 回應標頭。
cookies Cookie[] (選用) HTTP 回應 Cookie。
body any (選用) HTTP 回應本文。
statusCode number (選用) HTTP 回應狀態碼。 如果未設定,則預設為 200
status number (選用) statusCode相同。 如果 statusCode 已設定,則會忽略這個屬性。

您也可以修改物件, context.res 而不覆寫物件。 默認 context.res 物件會使用 HttpResponseFull 介面,除了 HttpResponseSimple 屬性之外,還支援下列方法:

方法 描述
status() 設定狀態。
setHeader() 設定標頭欄位。 注意: res.set() 也支援 和 res.header() ,並執行相同的動作。
getHeader() 取得標頭欄位。 注意: res.get() 也受到支援,而且會執行相同的動作。
removeHeader() 拿掉標頭。
type() 設定 「content-type」 標頭。
send() 此方法已淘汰。 它會設定主體和呼叫 context.done() ,表示同步函式已完成。 注意: res.end() 也受到支援,而且會執行相同的動作。
sendStatus() 此方法已淘汰。 它會設定狀態代碼和呼叫 context.done() ,以指出同步函式已完成。
json() 此方法已淘汰。 它會將 「content-type」 設定為 「application/json」、設定主體,以及呼叫 context.done() 以指出同步函式已完成。

回應可以透過數種方式來設定:

  • 作為類型的 HttpResponseInit簡單介面: 此選項是傳回回應的最簡潔方式。

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

    介面 HttpResponseInit 具有下列屬性:

    屬性 類型​ 描述
    body BodyInit (選用) HTTP 回應本文做為 、AsyncIterable<Uint8Array>、、、BlobFormDataIterable<Uint8Array>NodeJS.ArrayBufferViewURLSearchParamsnullstringArrayBuffer其中一個。
    jsonBody any (選用) JSON 可串行化的 HTTP 回應主體。 如果設定, HttpResponseInit.body 則會忽略 屬性,以偏向這個屬性。
    status number (選用) HTTP 回應狀態碼。 如果未設定,則預設為 200
    headers HeadersInit (選用) HTTP 回應標頭。
    cookies Cookie[] (選用) HTTP 回應 Cookie。
  • 做為類型 HttpResponse為 的類別: 此選項提供協助程式方法來讀取和修改響應的各個部分,例如標頭。

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

    類別 HttpResponse 接受選擇性 HttpResponseInit 做為其建構函式的自變數,並具有下列屬性:

    屬性 類型​ 描述
    status number HTTP 回應狀態碼。
    headers Headers HTTP 回應標頭。
    cookies Cookie[] HTTP 回應 Cookie。
    body ReadableStream | null 主體為可讀取數據流。
    bodyUsed boolean 布爾值,指出本文是否已讀取。

HTTP 資料流 (預覽)

HTTP 數據流是一項功能,可讓您更輕鬆地處理大型數據、串流 OpenAI 回應、提供動態內容,以及支援其他核心 HTTP 案例。 它可讓您將要求串流至 Node.js 函式應用程式中的 HTTP 端點和回應。 在您的應用程式需要透過 HTTP 進行用戶端與伺服器之間的即時交換和互動的情況下,使用 HTTP 串流。 使用 HTTP 時,您也可以使用 HTTP 串流來取得應用程式的最佳效能和可靠性。

HTTP 數據流目前為預覽狀態。

重要

v3 模型中不支援 HTTP 數據流。 升級至 v4 模型 以使用 HTTP 串流功能。

程序設計模型 v4 中的現有 HttpRequestHttpResponse 類型已經支援處理訊息本文的各種方式,包括作為數據流。

必要條件

啟用數據流

使用下列步驟,在 Azure 和本機項目中啟用函式應用程式中的 HTTP 串流:

  1. 如果您打算串流大量數據,請修改 FUNCTIONS_REQUEST_BODY_SIZE_LIMIT Azure 中的設定。 允許的默認主體大小上限是 104857600,這會將您的要求限制為 ~100 MB 的大小。

  2. 針對本機開發,也新增 FUNCTIONS_REQUEST_BODY_SIZE_LIMITlocal.settings.json 檔案

  3. 在主欄位包含的任何檔案中,將下列程式代碼新增至您的應用程式

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

資料流範例

此範例顯示 HTTP 觸發的函式,該函式會透過 HTTP POST 要求接收數據,而函式會將此資料串流至指定的輸出檔:

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

此範例顯示 HTTP 觸發的函式,此函式會將檔案的內容串流為傳入 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 };
    },
});

串流考慮

  • request.params在預覽期間使用 HTTP 資料流時,不支持物件。 如需詳細資訊和建議的因應措施,請參閱此 GitHub 問題

  • 使用 request.body 以取得使用數據流的最大優點。 您仍然可以繼續使用 之類的 request.text()方法,一律會將本文傳回為字串。

勾點

v3 模型中不支援勾點。 升級至 v4 模型 以使用勾點。

使用勾點在 Azure Functions 生命週期中的不同點執行程式代碼。 攔截會依註冊的順序執行,而且可以從您應用程式中的任何檔案註冊。 目前有兩個攔截範圍:「應用程式」層級和「叫用」層級。

叫用勾點

每次叫用函式時,叫用攔截或攔截之後, preInvocation 每次叫用函式執行一 postInvocation 次。 根據預設,您的攔截會針對所有觸發程式類型執行,但您也可以依類型進行篩選。 下列範例示範如何依觸發程式類型註冊叫用攔截和篩選:

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

攔截處理程式的第一個自變數是該攔截類型特定的內容物件。

物件 PreInvocationContext 具有下列屬性:

屬性 說明
inputs 傳遞至調用的自變數。
functionHandler 調用的函式處理程式。 此值的變更會影響函式本身。
invocationContext 傳遞至函式的調用內容物件。
hookData 在相同範圍中的勾點之間儲存和共用數據的建議位置。 您應該使用唯一的屬性名稱,使其與其他勾點的數據不衝突。

物件 PostInvocationContext 具有下列屬性:

屬性 說明
inputs 傳遞至調用的自變數。
result 函式的結果。 此值的變更會影響函式的整體結果。
error 函式擲回的錯誤,如果沒有錯誤,則為 null/undefined。 此值的變更會影響函式的整體結果。
invocationContext 傳遞至函式的調用內容物件。
hookData 在相同範圍中的勾點之間儲存和共用數據的建議位置。 您應該使用唯一的屬性名稱,使其與其他勾點的數據不衝突。

應用程式勾點

應用程式攔截會在您應用程式的每個實例執行一次,不論是在掛勾啟動 appStart 期間,還是在攔截終止期間 appTerminate 執行。 應用程式終止攔截的時間有限,而且在所有案例中都不會執行。

Azure Functions 運行時間目前 不支援 叫用外部的內容記錄。 使用 Application Insights npm 套件 在應用層級勾點期間記錄數據。

下列範例會註冊應用程式勾點:

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

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

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

攔截處理程式的第一個自變數是該攔截類型特定的內容物件。

物件 AppStartContext 具有下列屬性:

屬性 說明
hookData 在相同範圍中的勾點之間儲存和共用數據的建議位置。 您應該使用唯一的屬性名稱,使其與其他勾點的數據不衝突。

物件 AppTerminateContext 具有下列屬性:

屬性 說明
hookData 在相同範圍中的勾點之間儲存和共用數據的建議位置。 您應該使用唯一的屬性名稱,使其與其他勾點的數據不衝突。

調整和并行

根據預設,Azure Functions 會自動監視應用程式的負載,並視需要為Node.js建立更多主機實例。 Azure Functions 會針對不同的觸發程式類型使用內建(不可使用者設定)閾值來決定何時新增實例,例如 QueueTrigger 的訊息存留期和佇列大小。 如需詳細資訊,請參閱取用和 進階版 計劃的運作方式。

此調整行為足以讓許多Node.js應用程式使用。 針對 CPU 系結應用程式,您可以使用多種語言背景工作進程進一步改善效能。 您可以使用 FUNCTIONS_WORKER_PROCESS_COUNT 應用程式設定,將每個主機的背景工作進程數目從預設值 1 增加至最多 10 個。 然後,Azure Functions 會嘗試平均分散這些背景工作角色的同時函式調用。 此行為使得 CPU 密集函式阻止其他函式執行的可能性較低。 此設定適用於 Azure Functions 在相應放大應用程式以符合需求時所建立的每個主機。

警告

FUNCTIONS_WORKER_PROCESS_COUNT請謹慎使用 設定。 在相同實例中執行的多個進程可能會導致無法預期的行為,並增加函式載入時間。 如果您使用此設定, 強烈建議 您從 套件檔案執行來抵消這些缺點。

節點版本

您可以從任何函式記錄 process.version ,查看運行時間正在使用的目前版本。 如需每個程式設計模型支援的Node.js版本清單,請參閱 supported versions

設定節點版本

您升級Node.js版本的方式取決於函式應用程式執行所在的作業系統。

在 Windows 上執行時,應用程式設定會設定 WEBSITE_NODE_DEFAULT_VERSION Node.js版本。 您可以使用 Azure CLI 或在 Azure 入口網站 中更新此設定。

如需Node.js版本的詳細資訊,請參閱 支援的版本

升級您的Node.js版本之前,請確定您的函式應用程式是在最新版的 Azure Functions 運行時間上執行。 如果您需要升級您的運行時間版本,請參閱 將應用程式從 Azure Functions 3.x 版移轉至 4.x 版。

執行 Azure CLI az functionapp config appsettings set 命令,以更新在 Windows 上執行的函式應用程式Node.js版本:

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

這會設定WEBSITE_NODE_DEFAULT_VERSION支援之 ~20LTS 版本的應用程式設定

變更之後,您的函式應用程式會重新啟動。 若要深入瞭解 Node.js 的 Functions 支援,請參閱 語言執行平臺支持原則

環境變數

環境變數可用於操作秘密(連接字串、金鑰、端點等)或環境設定,例如分析變數。 您可以在本機和雲端環境中新增環境變數,並在函式程式代碼中透過 process.env 存取它們。

下列範例會 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"]}`);
}

在本機開發環境中

當您在本機執行時,函式專案會包含檔案local.settings.json,您可以在其中將環境變數儲存在物件中。Values

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

在 Azure 雲端環境中

當您在 Azure 中執行時,函式應用程式可讓您設定及使用應用程式設定,例如服務 連接字串,並在執行期間將這些設定公開為環境變數。

有數種方式可以新增、更新和刪除函式應用程式設定:

函式應用程式設定的變更需要重新啟動函式應用程式。

背景工作環境變數

Node.js有數個專屬的 Functions 環境變數:

languageWorkers__node__arguments

此設定可讓您在啟動Node.js程式時指定自訂自變數。 在本機最常用來在偵錯模式中啟動背景工作角色,但如果您需要自定義自變數,也可以在 Azure 中使用。

警告

可能的話,請避免在 Azure 中使用 languageWorkers__node__arguments ,因為它可能會對冷啟動時間產生負面影響。 運行時間必須使用自定義自變數從頭開始啟動新的背景工作角色,而不是使用預先準備的背景工作角色。

logging__logLevel__Worker

此設定會調整Node.js特定背景工作記錄的默認記錄層級。 根據預設,只會顯示警告或錯誤記錄檔,但您可以將它設定為 informationdebug ,以協助診斷Node.js背景工作角色的問題。 如需詳細資訊,請參閱 設定記錄層級

ECMAScript 模組 (預覽)

注意

由於 ECMAScript 模組目前是 Azure Functions Node.js 14 或更新版本中的預覽功能。

ECMAScript 模組 (ES 模組 ) 是適用於 Node.js 的新官方標準模組系統。 到目前為止,本文中的程式代碼範例會使用 CommonJS 語法。 在 Node.js 14 或更高版本中執行 Azure Functions 時,您可以選擇使用 ES 模組語法撰寫函式。

若要在函式中使用 ES 模組,請將其檔案名變更為 .mjs 使用延伸模組。 下列 index.mjs 檔案範例是使用 ES 模組語法匯入連結 uuid 庫並傳回值的 HTTP 觸發函式。

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

設定函式進入點

function.json屬性scriptFileentryPoint 可用來設定匯出函式的位置和名稱。 scriptFile當您使用 TypeScript 時,需要 屬性,而且應該指向已編譯的 JavaScript。

使用 scriptFile

根據預設,JavaScript 函式會從 index.js執行,該檔案會與其對應的 function.json共用相同的父目錄。

scriptFile 可用來取得看起來像下列範例的資料夾結構:

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

function.jsonmyFirstFunction 應該包含 scriptFile 指向要執行導出函式之檔案的屬性。

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

使用 entryPoint

在 v3 模型中,必須使用 匯出 module.exports 函式,才能找到並執行。 根據預設,觸發時執行的函式是唯一從該檔案匯出、名為 run的匯出,或名為 index的導出。 下列範例會將 中的 function.json 設定entryPoint為自訂值 「logHello」 :

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

module.exports = { logHello };

本機偵錯

建議您使用 VS Code 進行本機偵錯,這會在偵錯模式中自動啟動您的Node.js進程,併為您附加至進程。 如需詳細資訊,請參閱 在本機執行函式。

如果您使用其他工具來偵錯,或想要以手動方式在偵錯模式中啟動Node.js程式,請在 local.settings.json 中新增 。Values"languageWorkers__node__arguments": "--inspect"--inspect 變數會告訴Node.js在埠 9229 上接聽偵錯用戶端。 如需詳細資訊,請參閱 Node.js偵錯指南

建議

本節說明建議遵循Node.js應用程式的數個具影響力模式。

選擇單一 vCPU App Service 方案

當您建立使用App Service 方案的函式應用程式時,建議您選取單一 vCPU 方案,而不是具有多個 vCPU 的方案。 目前,Functions 會在單一 vCPU VM 上更有效率地執行Node.js函式,而使用較大的 VM 不會產生預期的效能改善。 必要時,您可以藉由新增更多單一 vCPU VM 實例來手動相應放大,也可以啟用自動調整。 如需詳細資訊,請參閱 手動或自動調整實例計數。

從套件檔案執行

當您在無伺服器裝載模型中開發 Azure Functions 時,冷啟動是現實。 冷啟動 是指函式應用程式在閑置一段時間后第一次啟動,需要較長的時間才能啟動。 對於Node.js具有大型相依性樹狀架構的應用程式,冷啟動可能相當重要。 若要加速冷啟動程式, 請盡可能以套件檔案的形式執行您的函式 。 根據預設,許多部署方法都會使用此模型,但如果您遇到大型冷啟動,您應該檢查以確定您是以這種方式執行。

使用單一靜態用戶端

當您在 Azure Functions 應用程式中使用服務特定用戶端時,請勿建立具有每個函式調用的新客戶端,因為您可以達到連線限制。 相反地,請在全域範圍中建立單一靜態用戶端。 如需詳細資訊,請參閱 管理 Azure Functions 中的連線。

使用 asyncawait

在Node.js中撰寫 Azure Functions 時,您應該使用 asyncawait 關鍵詞撰寫程序代碼。 使用和 來撰寫程序await代碼,而不是回async呼,或使用 .then.catch Promises 來協助避免兩個常見問題:

  • 擲回造成Node.js進程損毀的未攔截例外 狀況,可能會影響其他函式的執行。
  • 非預期的行為,例如來自的遺漏記錄 context.log,是由未正確等候的異步呼叫所造成。

在下列範例中,異步方法 fs.readFile 會叫用錯誤優先回呼函式作為其第二個參數。 此程式代碼會造成先前提到的兩個問題。 未在正確範圍中明確攔截的例外狀況可能會使整個進程當機(問題 #1)。 傳回而不確保回呼完成表示 HTTP 回應有時會有空本文 (問題 #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 };
    },
});

在下列範例中,異步方法 fs.readFile 會叫用錯誤優先回呼函式作為其第二個參數。 此程式代碼會造成先前提到的兩個問題。 未在正確範圍中明確攔截的例外狀況可能會使整個進程當機(問題 #1)。 在回呼範圍之外呼叫已被 context.done() 取代的方法,可以發出函式在讀取檔案之前完成的訊號(問題 #2)。 在此範例中,呼叫 context.done() 太早會導致從 開始 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使用和 await 關鍵詞來協助避免這兩個問題。 Node.js生態系統中的大多數 API 已轉換為支持某種形式的承諾。 例如,從 v14 開始,Node.js提供 fs/promises API 來取代回 fs 呼 API。

在下列範例中,在函式執行期間擲回的任何未處理的例外狀況只會讓引發例外狀況的個別調用失敗。 await關鍵詞表示後續readFile步驟只會在完成之後執行。

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

使用 asyncawait,您也不需要呼叫回 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}`);
}

疑難排解

請參閱疑難解答指南Node.js。

下一步

如需詳細資訊,請參閱以下資源: