移轉至適用於 Azure Functions 的第 4 版 Node.js 程式設計模型
本文討論 Node.js 程式設計模型第 3 版和第 4 版之間的差異,以及如何升級現有的第 3 版應用程式。 如果您想要建立新的第 4 版應用程式,而不是升級現有的第 3 版應用程式,請參閱 Visual Studio Code(VS Code) 或 Azure Functions Core Tools 教學課程。 本文使用「提示」警示,來醒目提示升級應用程式時應採取的最重要具體動作。
第 4 版的設計目的是為 Node.js 開發人員提供下列優點:
- 為 Node.js 開發人員提供熟悉且直覺的體驗。
- 讓檔案結構變得更彈性,並支援完整自訂。
- 切換至以程式碼為中心的方法來定義函式設定。
考量
- 不應將 Node.js 程式設計模型與 Azure Functions 執行階段混淆:
- 程式設計模型:定義您撰寫程式碼的方式,以及 JavaScript 和 TypeScript 特有的方式。
- 執行階段:定義 Azure Functions 的基礎行為,並跨所有語言共用。
- 程式設計模型的版本會嚴格地繫結至
@azure/functions
npm 套件版本。 此為獨立於執行階段的版本。 執行階段和程式設計模型都使用數字 4 作為其最新的主要版本,但這是巧合。 - 您無法在相同的函數應用程式中混合使用 v3 和 v4 程式設計模型。 一旦您在應用程式中註冊一個 v4 函式,function.json 檔案中註冊的任何 v3 函式就會遭到忽略。
需求
Node.js 程式設計模型的第 4 版需要下列最低版本:
@azure/functions
npm 套件 4.0.0 版- Node.js 18 以上的版本
- Azure Functions 執行階段 4.25 以上的版本
- Azure Functions Core Tools 4.0.5382 以上的版本 (如果在本機執行)
@azure/functions
npm 套件 4.0.0 版- Node.js 18 以上的版本
- TypeScript 4 以上的版本
- Azure Functions 執行階段 4.25 以上的版本
- Azure Functions Core Tools 4.0.5382 以上的版本 (如果在本機執行)
安裝 npm 套件
在第 4 版中,@azure/functions
npm 套件包含支援 Node.js 程式設計模型的主要原始程式碼。 在舊版中,該程式碼直接隨附於 Azure 中,而 npm 套件只有 TypeScript 類型。 您現在需要同時包含適用於 TypeScript 和 JavaScript 應用程式的此套件。 您可以包含現有第 3 版應用程式的套件,但不一定要這麼做。
提示
確保在 package.json 檔案中的 dependencies
區段 (而不是 devDependencies
) 會列出 @azure/functions
套件。 您可以使用下列命令來安裝第 4 版:
npm install @azure/functions
設定應用程式進入點
在程式設計模型的第 4 版中,您可以視需要建構程式碼。 應用程式根目錄中唯一需要的檔案是 host.json 和 package.json。
否則,您可以在 package.json 檔案中設定 main
欄位來定義檔案結構。 您可以使用 glob 模式,將 main
欄位設為單一檔案或多個檔案。 下表顯示 main
欄位的範例值:
範例 | 描述 |
---|---|
src/index.js |
從單一根檔案註冊函式。 |
src/functions/*.js |
從自己的檔案註冊每個函式。 |
src/{index.js,functions/*.js} |
組合可讓您從自己的檔案註冊每個函式,但您仍有一般應用層級程式碼的根檔案。 |
範例 | 描述 |
---|---|
dist/src/index.js |
從單一根檔案註冊函式。 |
dist/src/functions/*.js |
從自己的檔案註冊每個函式。 |
dist/src/{index.js,functions/*.js} |
組合可讓您從自己的檔案註冊每個函式,但您仍有一般應用層級程式碼的根檔案。 |
提示
請確定您在 package.json 檔案中定義 main
欄位。
切換引數的順序
觸發程序輸入 (而不是叫用內容) 現在是函式處理常式的第一個引數。 現在會在第 4 版中簡化第二個引數的叫用內容,而且不會像觸發程序輸入一樣需要該叫用內容。 如果不會用到該內容,則可以將其排除。
提示
切換引數的順序。 例如,如果您使用 HTTP 觸發程序,請將 (context, request)
切換至 (request, context)
,或是在不使用內容時就切換至 (request)
。
在程式碼中定義函式
您不再需要建立和維護這些個別的 function.json 設定檔。 您現在可以直接在 TypeScript 或 JavaScript 檔案中完整定義函式。 此外,許多屬性現在都有預設值,因此您不需要每次都得指定值。
const { app } = require('@azure/functions');
app.http('httpTrigger1', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || (await request.text()) || 'world';
return { body: `Hello, ${name}!` };
},
});
import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions';
export async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
context.log(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || (await request.text()) || 'world';
return { body: `Hello, ${name}!` };
}
app.http('httpTrigger1', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: httpTrigger1,
});
提示
將設定從 function.json 檔案移至程式碼。 觸發程序的類別會對應至新模型中 app
物件上的方法。 例如,如果您在 function.json 中使用 httpTrigger
類別,請在程式碼中呼叫 app.http()
以註冊函式。 如果您使用 timerTrigger
,請呼叫 app.timer()
。
檢閱內容的使用方式
在第 4 版中,context
物件會經過簡化以減少重複,並讓撰寫單元測試的過程變得更輕鬆。 例如,我們已簡化主要輸入和輸出,以便僅存取這些項目作為函式處理常式的引數和傳回值。
您無法再存取 context
物件上的主要輸入和輸出,但仍必須存取 context
物件上的次要輸入和輸出。 如需次要輸入和輸出的詳細資訊,請參閱 Node.js 開發人員指南。
取得主要輸入作為引數
主要輸入也稱為觸發程序,而且是唯一必要的輸入或輸出。 您必須有一個 (且只有一個) 觸發程序。
第 4 版僅支援取得觸發程序輸入 (作為第一個引數) 的一種方式:
async function httpTrigger1(request, context) {
const onlyOption = request;
async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
const onlyOption = request;
提示
請確定您未使用 context.req
或 context.bindings
來取得輸入。
將主要輸出設定為傳回值
第 4 版僅支援透過傳回值設定主要輸出的一種方式:
return {
body: `Hello, ${name}!`
};
async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
// ...
return {
body: `Hello, ${name}!`
};
}
提示
請確定您一律會傳回函式處理常式中的輸出,而不是使用 context
物件來設定輸出。
內容記錄
如下列範例所示,在第 4 版中,記錄方法已移至根 context
物件。 如需記錄的詳細資訊,請參閱 Node.js 開發人員指南。
context.log('This is an info log');
context.error('This is an error');
context.warn('This is an error');
建立測試內容
第 3 版不支援在 Azure Functions 執行階段外部建立叫用內容,因此單元測試的撰寫可能很困難。 第 4 版可讓您建立叫用內容的執行個體,除非您自行新增,否則測試期間的資訊並不詳細。
const testInvocationContext = new InvocationContext({
functionName: 'testFunctionName',
invocationId: 'testInvocationId'
});
檢閱 HTTP 類型的使用方式
HTTP 要求和回應類型現在是擷取標準的一部分。 這些類型對於 Azure Functions 不再是唯一的。
這些類型會在 Node.js 中使用 undici
套件。 此套件遵循擷取標準,目前已整合至 Node.js 核心。
HttpRequest
本文。 您可以使用您要接收之類型的特定方法來存取主體:
const body = await request.text(); const body = await request.json(); const body = await request.formData(); const body = await request.arrayBuffer(); const body = await request.blob();
標頭:
const header = request.headers.get('content-type');
查詢參數:
const name = request.query.get('name');
HttpResponse
狀態:
return { status: 200 };
本文:
使用
body
屬性可傳回大部分的類型,例如string
或Buffer
:return { body: "Hello, world!" };
使用
jsonBody
屬性,以最簡單的方式傳回 JSON 回應:return { jsonBody: { hello: "world" } };
標頭。 視使用的
HttpResponse
類別或HttpResponseInit
介面而定,您可以透過兩種方式來設定標頭:const response = new HttpResponse(); response.headers.set('content-type', 'application/json'); return response;
return { headers: { 'content-type': 'application/json' } };
提示
使用與新方法相符的 HTTP 要求或回應類型,來更新任何邏輯。
提示
使用與新方法相符的 HTTP 要求或回應類型,來更新任何邏輯。 您應該會收到 TypeScript 建置錯誤,以協助識別您是否使用舊方法。
疑難排解
請參閱 Node.js 疑難排解指南。