迁移到适用于 Azure Functions 的 Node.js 编程模型版本 4
本文讨论 Node.js 编程模型版本 3 和版本 4 之间的差异,以及如何升级现有 v3 应用。 如果要创建新的 v4 应用而不是升级现有 v3 应用,请参阅面向 Visual Studio Code (VS Code) 或 Azure Functions Core Tools 的教程。 本文使用“提示”提醒来突出显示升级应用时应采取的最重要的具体操作。
版本 4 旨在为 Node.js 开发人员提供以下权益:
- 为 Node.js 开发人员提供熟悉且直观的体验。
- 通过支持完全自定义,增强文件结构的灵活性。
- 切换到以代码为中心的方法来定义函数配置。
注意事项
注意
Node.js 编程模型的版本 4 目前为公共预览版。
- 在预览期间,v4 模型要求将应用设置
AzureWebJobsFeatureFlags
设为EnableWorkerIndexing
。 有关详细信息,请参阅启用 v4 编程模型。 - 不应将 Node.js“编程模型”与 Azure Functions“运行时”混淆。
- 编程模型:定义代码的创作方式,并特定于 JavaScript 和 TypeScript。
- 运行时:定义 Azure Functions 的基础行为,并在所有语言之间共享。
- 编程模型版本严格绑定到
@azure/functions
npm 包的版本,并且独立于运行时进行版本控制。 运行时和编程模型都使用“4”作为其最新主版本,但这纯粹是巧合。 - 请记住,不能在同一函数应用中混用 v3 和 v4 编程模型。 在应用中注册一个 v4 函数后,
function.json
文件中注册的任何 v3 函数都将被忽略。
要求
Node.js 编程模型的版本 4 需要以下最低版本:
@azure/functions
npm 包 v4.0.0- Node.js v18+
- Azure Functions 运行时 v4.25+
- Azure Functions Core Tools v4.0.5382+(如果在本地运行)
@azure/functions
npm 包 v4.0.0- Node.js v18+
- TypeScript v4+
- Azure Functions 运行时 v4.25+
- Azure Functions Core Tools v4.0.5382+(如果在本地运行)
加入 npm 包
在 v4 中,@azure/functions
npm 包中包含了支持 Node.js 编程模型的主要源代码。 在以前的版本中,该代码直接在 Azure 中提供,而 npm 包仅具有 TypeScript 类型。 现在,需要将此包加入 TypeScript 和 JavaScript 应用中。 你可以加入现有 v3 应用的包,但这不是必需的。
提示
确保 @azure/functions
包在 package.json 文件的 dependencies
部分(而不是 devDependencies
)中列出。 可以使用以下命令安装 v4:
npm install @azure/functions
设置应用入口点
在编程模型的 v4 中,可以根据需要构建代码。 在应用的根目录中,仅需要 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
字段。
切换参数的顺序
现在,触发器输入(而不是调用上下文)是函数处理程序的第一个参数。 调用上下文(现在是第二个参数)已在 v4 中简化,并且不像触发器输入一样必需。 如果不使用它,则可以将其禁用。
提示
切换参数的顺序。 例如,如果你使用的是 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()
。
查看上下文的使用情况
在 v4 中,已对 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
对象对其进行设置。
上下文日志记录
在 v4 中,日志记录方法已移动到根 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 故障排除指南。