Azure Functions JavaScript 开发人员指南Azure Functions JavaScript developer guide

本指南包含有关使用 JavaScript 编写 Azure Functions 的复杂性的信息。This guide contains information about the intricacies of writing Azure Functions with JavaScript.

JavaScript 函数是导出的 function,它将在触发时执行(触发器在 function.json 中配置)。A JavaScript function is an exported function that executes when triggered (triggers are configured in function.json). 传递给每个函数的第一个参数是 context 对象,该对象用于接收和发送绑定数据、日志记录以及与运行时通信。The first argument passed to every function is a context object, which is used for receiving and sending binding data, logging, and communicating with the runtime.

本文假定你已阅读 Azure Functions 开发人员参考This article assumes that you have already read the Azure Functions developer reference. 完成有关使用 Visual Studio Code门户创建第一个函数的 Functions 快速入门。Complete the Functions quickstart to create your first function, using Visual Studio Code or in the portal.

本文也支持 TypeScript 应用开发This article also supports TypeScript app development.

文件夹结构Folder structure

JavaScript 项目所需的文件夹结构如下所示。The required folder structure for a JavaScript project looks like the following. 可更改此默认值。This default can be changed. 有关详细信息,请参阅下面的 scriptFile 部分。For more information, see the scriptFile section below.

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

项目的根目录中有共享的 host.json 文件,可用于配置函数应用。At the root of the project, there's a shared host.json file that can be used to configure the function app. 每个函数都具有一个文件夹,其中包含其代码文件 (.js) 和绑定配置文件 (function.json)。Each function has a folder with its own code file (.js) and binding configuration file (function.json). function.json 父目录的名称始终是函数的名称。The name of function.json's parent directory is always the name of your function.

2.x 版 Functions 运行时中所需的绑定扩展在 extensions.csproj 文件中定义,实际库文件位于 bin 文件夹中。The binding extensions required in version 2.x of the Functions runtime are defined in the extensions.csproj file, with the actual library files in the bin folder. 本地开发时,必须注册绑定扩展When developing locally, you must register binding extensions. 在 Azure 门户中开发函数时,系统将为你完成此注册。When developing functions in the Azure portal, this registration is done for you.

导出函数Exporting a function

必须通过 module.exports(或 exports)导出 JavaScript 函数。JavaScript functions must be exported via module.exports (or exports). 导出的函数应是触发时执行的 JavaScript 函数。Your exported function should be a JavaScript function that executes when triggered.

默认情况下,Functions 运行时会在 index.js 中查找你的函数,其中,index.js 与其相应的 function.json 共享同一个父目录。By default, the Functions runtime looks for your function in index.js, where index.js shares the same parent directory as its corresponding function.json. 默认情况下,导出的函数应该是其文件中的唯一导出,或者名为 runindex 的导出。In the default case, your exported function should be the only export from its file or the export named run or index. 若要配置文件位置和导出函数名称,请阅读下面的配置函数的入口点To configure the file location and export name of your function, read about configuring your function's entry point below.

在执行时,将为导出的函数传递一些参数。Your exported function is passed a number of arguments on execution. 采用的第一个参数始终是 context 对象。The first argument it takes is always a context object. 如果函数是同步的(不返回 Promise),则必须传递 context 对象,因为需要调用 context.done 才能正常使用该函数。If your function is synchronous (does not return a Promise), you must pass the context object, as calling context.done is required for correct use.

// You should include context, other arguments are optional
module.exports = function(context, myTrigger, myInput, myOtherInput) {
    // function logic goes here :)
    context.done();
};

导出异步函数Exporting an async function

在 Functions 运行时版本 2.x 中使用 async function 声明或普通 JavaScript Promise,无需显式调用 context.done 回调即可通知函数已完成。When using the async function declaration or plain JavaScript Promises in version 2.x of the Functions runtime, you do not need to explicitly call the context.done callback to signal that your function has completed. 导出的异步函数/Promise 完成时,函数将完成。Your function completes when the exported async function/Promise completes. 对于面向版本 1.x 运行时的函数,在代码完成执行后,仍必须调用 context.doneFor functions targeting the version 1.x runtime, you must still call context.done when your code is done executing.

以下示例是一个简单的函数,用于记录其已被触发并立即完成执行。The following example is a simple function that logs that it was triggered and immediately completes execution.

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

导出异步函数时,还可配置输出绑定,以使用 return 值。When exporting an async function, you can also configure an output binding to take the return value. 如果只有一个输出绑定,则建议使用此值。This is recommended if you only have one output binding.

若要使用 return 分配输出,请在 function.json 中将 name 属性更改为 $returnTo assign an output using return, change the name property to $return in function.json.

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

在这种情况下,函数应如以下示例所示:In this case, your function should look like the following example:

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

绑定Bindings

在 JavaScript 中,需在函数的 function.json 中配置和定义绑定In JavaScript, bindings are configured and defined in a function's function.json. 函数通过多种方式来与绑定交互。Functions interact with bindings a number of ways.

输入Inputs

在 Azure Functions 中,输入分为两种类别:一种是触发器输入,另一种则是附加输入。Input are divided into two categories in Azure Functions: one is the trigger input and the other is the additional input. 函数可通过三种方式读取触发器和其他输入绑定(direction === "in" 的绑定):Trigger and other input bindings (bindings of direction === "in") can be read by a function in three ways:

  • [建议] 以传递给函数的参数的形式。[Recommended] As parameters passed to your function. 它们以与 function.json 中定义的顺序相同的顺序传递给函数。They are passed to the function in the same order that they are defined in function.json. function.json 中定义的 name 属性不需要与参数名称匹配,不过两者应该匹配。The name property defined in function.json does not need to match the name of your parameter, although it should.

    module.exports = async function(context, myTrigger, myInput, myOtherInput) { ... };
    
  • context.bindings 对象的成员的形式。As members of the context.bindings object. 每个成员由 function.json 中定义的 name 属性命名。Each member is named by the name property defined in 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);
    };
    
  • 使用 JavaScript arguments 对象以输入的形式。As inputs using the JavaScript arguments object. 这实质上与作为参数传递输入相同,但可以动态处理输入。This is essentially the same as passing inputs as parameters, but allows you to dynamically handle inputs.

    module.exports = async function(context) { 
        context.log("This is myTrigger: " + arguments[1]);
        context.log("This is myInput: " + arguments[2]);
        context.log("This is myOtherInput: " + arguments[3]);
    };
    

OutputsOutputs

函数可通过多种方式写入输出(direction === "out" 的绑定)。Outputs (bindings of direction === "out") can be written to by a function in a number of ways. 在所有情况下,function.json 中定义的绑定属性 name 对应于函数中所写入到的对象成员的名称。In all cases, the name property of the binding as defined in function.json corresponds to the name of the object member written to in your function.

可通过以下方式之一将数据分配到输出绑定(不要结合使用这些方法):You can assign data to output bindings in one of the following ways (don't combine these methods):

  • [有多个输出时建议使用] 返回对象。[Recommended for multiple outputs] Returning an object. 如果使用异步函数/返回 Promise 的函数,可以返回分配有输出数据的对象。If you are using a async/Promise returning function, you can return an object with assigned output data. 在以下示例中,function.json 中的输出绑定名为“httpResponse”和“queueOutput”。In the example below, the output bindings are named "httpResponse" and "queueOutput" in function.json.

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

    如果使用同步函数,可以使用 context.done 返回此对象(请参阅示例)。If you are using a synchronous function, you can return this object using context.done (see example).

  • [有单个输出时建议使用] 直接返回值,并使用 $return 绑定名称。[Recommended for single output] Returning a value directly and using the $return binding name. 这仅适用于异步函数/返回 Promise 的函数。This only works for async/Promise returning functions. 请参阅导出异步函数中的示例。See example in exporting an async function.

  • context.bindings 赋值 可以直接向 context.bindings 赋值。Assigning values to context.bindings You can assign values directly to context.bindings.

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

绑定数据类型Bindings data type

若要定义输入绑定的数据类型,请使用绑定定义中的 dataType 属性。To define the data type for an input binding, use the dataType property in the binding definition. 例如,若要以二进制格式读取 HTTP 请求的内容,请使用类型 binaryFor example, to read the content of an HTTP request in binary format, use the type binary:

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

dataType 的选项为 binarystreamstringOptions for dataType are: binary, stream, and string.

上下文对象context object

运行时使用 context 对象将数据传入和传出函数,并能与其进行通信。The runtime uses a context object to pass data to and from your function and to let you communicate with the runtime. 上下文对象可用于从绑定读取和设置数据、写入日志,以及当导出的函数是同步函数时使用 context.done 回调。The context object can be used for reading and setting data from bindings, writing logs, and using the context.done callback when your exported function is synchronous.

context 对象始终是传递给函数的第一个参数。The context object is always the first parameter to a function. 之所以需要包含此对象,是因为它包含 context.donecontext.log 等重要方法。It should be included because it has important methods such as context.done and context.log. 可以按个人喜好为对象命名(例如 ctxc)。You can name the object whatever you would like (for example, ctx or c).

// You must include a context, but other arguments are optional
module.exports = function(ctx) {
    // function logic goes here :)
    ctx.done();
};

context.bindings 属性context.bindings property

context.bindings

返回一个包含所有输入和输出数据的已命名对象。Returns a named object that contains all your input and output data. 例如,function.json 中的以下绑定定义允许通过 context.bindings.myInput 访问队列的内容和使用 context.bindings.myOutput 将输出分配给队列。For example, the following binding definitions in your function.json let you access the contents of a queue from context.bindings.myInput and assign outputs to a queue using context.bindings.myOutput.

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

可以选择使用 context.done 方法而不是 context.binding 对象来定义输出绑定数据(参阅下文)。You can choose to define output binding data using the context.done method instead of the context.binding object (see below).

context.bindingData 属性context.bindingData property

context.bindingData

返回包含触发器元数据和函数调用数据(invocationIdsys.methodNamesys.utcNowsys.randGuid)的命名对象。Returns a named object that contains trigger metadata and function invocation data (invocationId, sys.methodName, sys.utcNow, sys.randGuid). 有关触发器元数据的示例,请参阅此事件中心示例For an example of trigger metadata, see this event hubs example.

context.done 方法context.done method

context.done([err],[propertyBag])

让运行时知道代码已完成。Lets the runtime know that your code has completed. 如果函数使用 async function 声明,则你不需要使用 context.done()When your function uses the async function declaration, you do not need to use context.done(). context.done 回调是隐式调用的。The context.done callback is implicitly called. 异步函数在 Node 8 或更高版本(需要 Functions 运行时版本 2.x)中可用。Async functions are available in Node 8 or a later version, which requires version 2.x of the Functions runtime.

如果函数不是异步函数,则必须调用 context.done 来告知运行时函数是完整的。If your function is not an async function, you must call context.done to inform the runtime that your function is complete. 如果缺少它,则执行将会超时。The execution times out if it is missing.

使用 context.done 方法可向运行时传回用户定义的错误,以及传回包含输出绑定数据的 JSON 对象。The context.done method allows you to pass back both a user-defined error to the runtime and a JSON object containing output binding data. 传递给 context.done 的属性将覆盖 context.bindings 对象上设置的任何内容。Properties passed to context.done overwrite anything set on the context.bindings object.

// Even though we set myOutput to have:
//  -> text: 'hello world', number: 123
context.bindings.myOutput = { text: 'hello world', number: 123 };
// If we pass an object to the done function...
context.done(null, { myOutput: { text: 'hello there, world', noNumber: true }});
// the done method overwrites the myOutput binding to be: 
//  -> text: 'hello there, world', noNumber: true

context.log 方法context.log method

context.log(message)

用于在默认跟踪级别写入到流函数日志。Allows you to write to the streaming function logs at the default trace level. context.log 中还提供了其他的日志记录方法,用以允许在其他跟踪级别向函数日志进行写入:On context.log, additional logging methods are available that let you write function logs at other trace levels:

方法Method 说明Description
error(message)error(message) 向错误级日志记录或更低级别进行写入。Writes to error level logging, or lower.
warn(message)warn(message) 向警告级日志记录或更低级别进行写入。Writes to warning level logging, or lower.
info(message)info(message) 向信息级日志记录或更低级别进行写入。Writes to info level logging, or lower.
verbose(message)verbose(message) 向详细级日志记录进行写入。Writes to verbose level logging.

以下示例在警告跟踪级别向日志进行写入:The following example writes a log at the warning trace level:

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

可以在 host.json 文件中为日志记录配置跟踪级别阈值You can configure the trace-level threshold for logging in the host.json file. 有关写入日志的详细信息,请参阅下面的写入跟踪输出For more information on writing logs, see writing trace outputs below.

将跟踪输出写入到控制台Writing trace output to the console

在 Functions 中,可以使用 context.log 方法将跟踪输出写入到控制台。In Functions, you use the context.log methods to write trace output to the console. 在 Functions v2.x 中,使用 console.log 的跟踪输出在函数应用级别捕获。In Functions v2.x, trace outputs using console.log are captured at the Function App level. 这意味着来自 console.log 的输出不受限于特定的函数调用,因此不会显示在特定函数的日志中。This means that outputs from console.log are not tied to a specific function invocation, and hence aren't displayed in a specific function's logs. 在 Functions v1.x 中,不能使用 console.log 写入到控制台。In Functions v1.x, you cannot use console.log to write to the console.

调用 context.log() 时,消息会在默认跟踪级别(即_信息_跟踪级别)写入到控制台。When you call context.log(), your message is written to the console at the default trace level, which is the info trace level. 以下代码在信息跟踪级别向控制台进行写入:The following code writes to the console at the info trace level:

context.log({hello: 'world'});  

此代码等同于上述代码:This code is equivalent to the code above:

context.log.info({hello: 'world'});  

此代码在错误级别向控制台进行写入:This code writes to the console at the error level:

context.log.error("An error has occurred.");  

因为_错误_是最高跟踪级别,所以,只要启用了日志记录,此跟踪会在所有跟踪级别写入到输出中。Because error is the highest trace level, this trace is written to the output at all trace levels as long as logging is enabled.

所有 context.log 方法都支持 Node.js util.format 方法支持的同一参数格式。All context.log methods support the same parameter format that's supported by the Node.js util.format method. 以下代码使用默认跟踪级别向函数日志进行写入:Consider the following code, which writes function logs by using the default trace level:

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

还可以采用以下格式编写同一代码:You can also write the same code in the following format:

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

为控制台日志记录配置跟踪级别Configure the trace level for console logging

Functions 1.x 允许定义向控制台进行写入时使用的阈值跟踪级别,这使得可以轻松控制从函数向控制台写入跟踪的方式。Functions 1.x lets you define the threshold trace level for writing to the console, which makes it easy to control the way traces are written to the console from your function. 若要针对写入到控制台的所有跟踪设置阈值,请在 host.json 文件中使用 tracing.consoleLevel 属性。To set the threshold for all traces written to the console, use the tracing.consoleLevel property in the host.json file. 此设置应用于 Function App 中的所有函数。This setting applies to all functions in your function app. 以下示例设置跟踪阈值来启用详细日志记录:The following example sets the trace threshold to enable verbose logging:

{
    "tracing": {
        "consoleLevel": "verbose"
    }
}  

consoleLevel 的值对应于 context.log 方法的名称。Values of consoleLevel correspond to the names of the context.log methods. 要为控制台禁用所有跟踪日志记录,请将 consoleLevel 设置为 offTo disable all trace logging to the console, set consoleLevel to off. 有关详细信息,请参阅 host.json 参考For more information, see host.json reference.

HTTP 触发器和绑定HTTP triggers and bindings

HTTP 和 webhook 触发器以及 HTTP 输出绑定使用请求和响应对象来表示 HTTP 消息。HTTP and webhook triggers and HTTP output bindings use request and response objects to represent the HTTP messaging.

请求对象Request object

context.req(请求)对象具有以下属性:The context.req (request) object has the following properties:

属性Property 说明Description
bodybody 一个包含请求正文的对象。An object that contains the body of the request.
headersheaders 一个包含请求标头的对象。An object that contains the request headers.
methodmethod 请求的 HTTP 方法。The HTTP method of the request.
originalUrloriginalUrl 请求的 URL。The URL of the request.
paramsparams 一个包含请求的路由参数的对象。An object that contains the routing parameters of the request.
queryquery 一个包含查询参数的对象。An object that contains the query parameters.
rawBodyrawBody 字符串形式的消息正文。The body of the message as a string.

响应对象Response object

context.res(响应)对象具有以下属性:The context.res (response) object has the following properties:

属性Property 说明Description
bodybody 一个包含响应正文的对象。An object that contains the body of the response.
headersheaders 一个包含响应标头的对象。An object that contains the response headers.
isRawisRaw 指示是否为响应跳过格式设置。Indicates that formatting is skipped for the response.
statusstatus 响应的 HTTP 状态代码。The HTTP status code of the response.

访问请求和响应Accessing the request and response

使用 HTTP 触发器时,可采用多种方式来访问 HTTP 响应和请求对象:When you work with HTTP triggers, you can access the HTTP request and response objects in a number of ways:

  • 通过 context 对象的 reqres 属性。From req and res properties on the context object. 采用此方式时,可以使用传统模式通过上下文对象访问 HTTP 数据,而不必使用完整的 context.bindings.name 模式。In this way, you can use the conventional pattern to access HTTP data from the context object, instead of having to use the full context.bindings.name pattern. 以下示例展示了如何访问 context 上的 reqres 对象:The following example shows how to access the req and res objects on the context:

    // You can access your http request off the context ...
    if(context.req.body.emoji === ':pizza:') context.log('Yay!');
    // and also set your http response
    context.res = { status: 202, body: 'You successfully ordered more coffee!' }; 
    
  • 通过已命名的输入和输出绑定。From the named input and output bindings. 采用此方式时,HTTP 触发器和绑定的工作方式与其他绑定相同。In this way, the HTTP trigger and bindings work the same as any other binding. 以下示例使用已命名的 response 绑定设置响应对象:The following example sets the response object by using a named response binding:

    {
        "type": "http",
        "direction": "out",
        "name": "response"
    }
    
    context.bindings.response = { status: 201, body: "Insert succeeded." };
    
  • [仅响应] 通过调用 context.res.send(body?: any)[Response only] By calling context.res.send(body?: any). HTTP 响应是使用输入 body 作为响应正文创建的。An HTTP response is created with input body as the response body. 隐式调用 context.done()context.done() is implicitly called.

  • [仅响应] 通过调用 context.done()[Response only] By calling context.done(). 有一种特殊的 HTTP 绑定可返回传递到 context.done() 方法的响应。A special kind of HTTP binding returns the response that is passed to the context.done() method. 以下 HTTP 输出绑定定义了一个 $return 输出参数:The following HTTP output binding defines a $return output parameter:

    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
    
     // Define a valid response object.
    res = { status: 201, body: "Insert succeeded." };
    context.done(null, res);   
    

Node 版本Node version

下表显示了 Functions 运行时的每个主要版本使用的 Node.js 版本:The following table shows the Node.js version used by each major version of the Functions runtime:

Functions 版本Functions version Node.js 版本Node.js version
1.x1.x 6.11.2(运行时锁定)6.11.2 (locked by the runtime)
2.x2.x 活动 LTS 和偶数的_最新_ Node.js 版本(推荐 8.11.1 和 10.14.1)。Active LTS and even-numbered Current Node.js versions (8.11.1 and 10.14.1 recommended). 使用 WEBSITE_NODE_DEFAULT_VERSION 应用设置来设置版本。Set the version by using the WEBSITE_NODE_DEFAULT_VERSION app setting.

可以通过查看上述应用设置或打印任何函数的 process.version 来查看运行时正在使用的当前版本。You can see the current version that the runtime is using by checking the above app setting or by printing process.version from any function.

依赖项管理Dependency management

若要在 JavaScript 代码中使用社区库(如下面的示例所示),需要确保在 Azure 中的 Function App 上安装所有依赖项。In order to use community libraries in your JavaScript code, as is shown in the below example, you need to ensure that all dependencies are installed on your Function App in Azure.

// Import the underscore.js library
var _ = require('underscore');
var version = process.version; // version === 'v6.5.0'

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

Note

应当在 Function App 的根目录下定义一个 package.json 文件。You should define a package.json file at the root of your Function App. 定义该文件将允许应用中的所有函数共享所缓存的相同包,从而获得最佳性能。Defining the file lets all functions in the app share the same cached packages, which gives the best performance. 如果发生版本冲突,可以通过在具体函数的文件夹中添加一个 package.json 文件来解决冲突。If a version conflict arises, you can resolve it by adding a package.json file in the folder of a specific function.

部署过程中,从源控件中部署 Function App 时,存储库中存在的任何 package.json 文件都将在其文件夹中触发 npm installWhen deploying Function Apps from source control, any package.json file present in your repo, will trigger an npm install in its folder during deployment. 但在通过门户或 CLI 部署时,必须手动安装包。But when deploying via the Portal or CLI, you will have to manually install the packages.

可通过两种方法在 Function App 上安装包:There are two ways to install packages on your Function App:

使用依赖项部署Deploying with Dependencies

  1. 通过运行 npm install 在本地安装所有必需的包。Install all requisite packages locally by running npm install.

  2. 部署代码,并确保部署中包含 node_modules 文件夹。Deploy your code, and ensure that the node_modules folder is included in the deployment.

使用 KuduUsing Kudu

  1. 转到 https://<function_app_name>.scm.chinacloudsites.cnGo to https://<function_app_name>.scm.chinacloudsites.cn.

  2. 单击“调试控制台”,选择“CMD”。 > Click Debug Console > CMD.

  3. 转到 D:\home\site\wwwroot,然后将 package.json 文件拖到页面上半部分中的 wwwroot 文件夹上。Go to D:\home\site\wwwroot, and then drag your package.json file to the wwwroot folder at the top half of the page.
    还可采用其他方式将文件上传到 Function App。You can upload files to your function app in other ways also. 有关详细信息,请参阅如何更新 Function App 文件For more information, see How to update function app files.

  4. 上传 package.json 文件后,在 Kudu 远程执行控制台中运行 npm install 命令。After the package.json file is uploaded, run the npm install command in the Kudu remote execution console.
    此操作将下载 package.json 文件中指定的包并重新启动 Function App。This action downloads the packages indicated in the package.json file and restarts the function app.

环境变量Environment variables

在 Functions 中,服务连接字符串等应用设置在执行过程中将公开为环境变量。In Functions, app settings, such as service connection strings, are exposed as environment variables during execution. 可以使用 process.env 访问这些设置,如以下 GetEnvironmentVariable 函数中所示:You can access these settings using process.env, as shown here in the GetEnvironmentVariable function:

module.exports = function (context, myTimer) {
    var timeStamp = new Date().toISOString();

    context.log('Node.js timer trigger function ran!', timeStamp);
    context.log(GetEnvironmentVariable("AzureWebJobsStorage"));
    context.log(GetEnvironmentVariable("WEBSITE_SITE_NAME"));

    context.done();
};

function GetEnvironmentVariable(name)
{
    return name + ": " + process.env[name];
}

可以通过以下几种方法添加、更新和删除函数应用设置:There are several ways that you can add, update, and delete function app settings:

在本地运行时,可从 local.settings.json 项目文件读取应用设置。When running locally, app settings are read from the local.settings.json project file.

配置函数入口点Configure function entry point

function.json 属性 scriptFileentryPoint 可用于配置导出函数的位置和名称。The function.json properties scriptFile and entryPoint can be used to configure the location and name of your exported function. 转译 JavaScript 时,这些属性可能非常重要。These properties can be important when your JavaScript is transpiled.

使用 scriptFileUsing scriptFile

默认情况下通过 index.js(与其对应的 function.json 共享相同父目录的文件)执行 JavaScript 函数。By default, a JavaScript function is executed from index.js, a file that shares the same parent directory as its corresponding function.json.

scriptFile 可用于获取以下示例所示的文件夹结构:scriptFile can be used to get a folder structure that looks like the following example:

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

myNodeFunctionfunction.json 应包含 scriptFile 属性,该属性指向包含要运行的导出函数的文件。The function.json for myNodeFunction should include a scriptFile property pointing to the file with the exported function to run.

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

使用 entryPointUsing entryPoint

scriptFile(或 index.js)中,必须使用 module.exports 导出函数才能使其被找到和运行。In scriptFile (or index.js), a function must be exported using module.exports in order to be found and run. 默认情况下,触发时执行的函数是该文件的唯一导出(导出名为 runindex)。By default, the function that executes when triggered is the only export from that file, the export named run, or the export named index.

可以使用 function.json 中的 entryPoint 配置此项设置,如以下示例所示:This can be configured using entryPoint in function.json, as in the following example:

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

Functions v2.x 支持用户函数中的 this 参数,其中的函数代码可能如以下示例所示:In Functions v2.x, which supports the this parameter in user functions, the function code could then be as in the following example:

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

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

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

请在此示例中务必注意,尽管正在导出对象,但无法保证可保留两次执行之间的状态。In this example, it is important to note that although an object is being exported, there are no guarantees for preserving state between executions.

本地调试Local Debugging

使用 --inspect 参数启动时,Node.js 进程会在指定端口上侦听调试客户端。When started with the --inspect parameter, a Node.js process listens for a debugging client on the specified port. 在 Azure Functions 2.x 中,可以指定要传递到运行代码的 Node.js 进程中的参数,方法是添加环境变量或应用设置 languageWorkers:node:arguments = <args>In Azure Functions 2.x, you can specify arguments to pass into the Node.js process that runs your code by adding the environment variable or App Setting languageWorkers:node:arguments = <args>.

若要在本地进行调试,请在 local.settings.json 文件的 Values 下添加 "languageWorkers:node:arguments": "--inspect=5858",然后将调试程序附加到端口 5858。To debug locally, add "languageWorkers:node:arguments": "--inspect=5858" under Values in your local.settings.json file and attach a debugger to port 5858.

使用 VS Code 进行调试时,系统会使用项目的 launch.json 文件中的 port 值自动添加 --inspect 参数。When debugging using VS Code, the --inspect parameter is automatically added using the port value in the project's launch.json file.

在版本 1.x 中,设置 languageWorkers:node:arguments 将无效。In version 1.x, setting languageWorkers:node:arguments will not work. 可以在 Azure Functions Core Tools 中使用 --nodeDebugPort 参数来选择调试端口。The debug port can be selected with the --nodeDebugPort parameter on Azure Functions Core Tools.

TypeScriptTypeScript

如果将目标限定为 2.x 版 Functions 运行时,可以在 Azure Functions for Visual Studio CodeAzure Functions Core Tools 中使用支持 TypeScript 函数应用项目的模板创建函数应用。When you target version 2.x of the Functions runtime, both Azure Functions for Visual Studio Code and the Azure Functions Core Tools let you create function apps using a template that support TypeScript function app projects. 该模板会生成 package.jsontsconfig.json 项目文件,以方便使用这些工具从 TypeScript 代码转译、运行和发布 JavaScript 函数。The template generates package.json and tsconfig.json project files that make it easier to transpile, run, and publish JavaScript functions from TypeScript code with these tools.

生成的 .funcignore 文件用于指示将项目发布到 Azure 时会排除哪些文件。A generated .funcignore file is used to indicate which files are excluded when a project is published to Azure.

TypeScript 文件 (.ts) 转译为 dist 输出目录中的 JavaScript (.js) 文件。TypeScript files (.ts) are transpiled into JavaScript files (.js) in the dist output directory. TypeScript 模板使用 function.json 中的 scriptFile 参数来指示 dist 文件夹中相应 .js 文件的位置。TypeScript templates use the scriptFile parameter in function.json to indicate the location of the corresponding .js file in the dist folder. 模板使用 tsconfig.json 文件中的 outDir 参数设置输出位置。The output location is set by the template by using outDir parameter in the tsconfig.json file. 如果更改此设置或文件夹的名称,则运行时将找不到要运行的代码。If you change this setting or the name of the folder, the runtime is not able to find the code to run.

Note

1.x 版 Functions 运行时提供 TypeScript 的试验性支持。Experimental support for TypeScript exists version 1.x of the Functions runtime. 调用函数时,试验版本会将 TypeScript 文件转译为 JavaScript 文件。The experimental version transpiles TypeScript files into JavaScript files when the function is invoked. 在版本 2.x 中,此试验性支持已由工具驱动的方法取代,该方法在初始化主机之前以及部署期间执行转译。In version 2.x, this experimental support has been superseded by the tool-driven method that does transpilation before the host is initialized and during the deployment process.

在本地通过 TypeScript 项目进行开发和部署的方式取决于所用的开发工具。The way that you locally develop and deploy from a TypeScript project depends on your development tool.

Visual Studio CodeVisual Studio Code

Azure Functions for Visual Studio Code 扩展允许使用 TypeScript 开发函数。The Azure Functions for Visual Studio Code extension lets you develop your functions using TypeScript. Azure Functions 扩展要求安装 Core Tools。The Core Tools is a requirement of the Azure Functions extension.

若要在 Visual Studio Code 中创建 TypeScript 函数应用,只需在创建函数应用时选择 TypeScript,系统将要求你选择语言。To create a TypeScript function app in Visual Studio Code, you simply choose TypeScript when you create a function app and are asked to choose the language.

按下 F5 在本地运行应用时,会先执行转译,然后再初始化主机 (func.exe)。When you press F5 to run the app locally, transpilation is done before the host (func.exe) is initialized.

使用“部署到函数应用...”按钮将函数应用部署到 Azure 时,Azure Functions 扩展首先会基于 TypeScript 源文件生成一个可随时在生产环境中使用的 JavaScript 文件版本。When you deploy your function app to Azure using the Deploy to function app... button, the Azure Functions extension first generates a production-ready build of JavaScript files from the TypeScript source files.

Azure Functions Core ToolsAzure Functions Core Tools

若要使用 Core Tools 创建 TypeScript 函数应用项目,必须在创建函数应用时指定 typescript 语言选项。To create a TypeScript function app project using Core Tools, you must specify the typescript language option when you create your function app. 可通过以下方式之一执行此操作:You can do this in one of the following ways:

  • 运行 func init 命令,选择 node 作为语言堆栈,然后选择 typescriptRun the func init command, select node as your language stack, and then select typescript.

  • 运行 func init --worker-runtime typescript 命令。Run the func init --worker-runtime typescript command.

若要使用 Core Tools 在本地运行函数应用代码,请使用 npm start 命令,而不要使用 func host startTo run your function app code locally using Core Tools, use the npm start command, instead of func host start. npm start 命令等效于以下命令:The npm start command is equivalent to the following commands:

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

在使用 func azure functionapp publish 命令部署到 Azure 之前,必须先运行 npm run build:production 命令。Before you use the func azure functionapp publish command to deploy to Azure, you must first run the npm run build:production command. 此命令基于 TypeScript 源文件创建一个可通过 func azure functionapp publish 部署的、随时可在生产环境中使用的 JavaScript 文件版本。This command creates a production-ready build of JavaScript files from the TypeScript source files that can be deployed using func azure functionapp publish.

JavaScript 函数的注意事项Considerations for JavaScript functions

使用 JavaScript 函数时,请注意以下各节中的注意事项。When you work with JavaScript functions, be aware of the considerations in the following sections.

选择单 vCPU 应用服务计划Choose single-vCPU App Service plans

创建使用应用服务计划的函数应用时,建议选择单 vCPU 计划,而不是选择具有多个 vCPU 的计划。When you create a function app that uses the App Service plan, we recommend that you select a single-vCPU plan rather than a plan with multiple vCPUs. 目前,Functions 在单 vCPU VM 上运行 JavaScript 函数更为高效;使用更大的 VM 不会产生预期的性能提高。Today, Functions runs JavaScript functions more efficiently on single-vCPU VMs, and using larger VMs does not produce the expected performance improvements. 需要时,可以通过添加更多单 vCPU VM 实例来手动扩大,也可以启用自动缩放。When necessary, you can manually scale out by adding more single-vCPU VM instances, or you can enable auto-scale.

冷启动Cold Start

对于无服务器托管模型中开发 Azure Functions,冷启动已成为现实。When developing Azure Functions in the serverless hosting model, cold starts are a reality. “冷启动”是指在函数应用处于非活动状态一段时间后进行第一次启动时,将需要较长时间才能启动。Cold start refers to the fact that when your function app starts for the first time after a period of inactivity, it takes longer to start up. 具体而言,对于具有较大依赖项树的 JavaScript 函数,冷启动可能不足以解决问题。For JavaScript functions with large dependency trees in particular, cold start can be significant. 为了加快冷启动过程,请尽量以包文件的形式运行函数To speed up the cold start process, run your functions as a package file when possible. 许多部署方法默认使用包模型中的运行,但如果遇到大规模的冷启动而不是以这种方式运行,则此项更改可以提供明显的改善。Many deployment methods use the run from package model by default, but if you're experiencing large cold starts and are not running this way, this change can offer a significant improvement.

后续步骤Next steps

有关详细信息,请参阅以下资源:For more information, see the following resources: