Function 节点允许对传递通过它的消息运行 JavaScript 代码。
消息作为一个名为 msg
的对象传入。根据惯例,它将具有一个 msg.payload
属性,包含消息的主体。
其他节点可以向消息添加自己的属性,这些属性应在它们的文档中描述。
输入到 Function 节点的代码表示函数的 主体。最简单的函数仅仅返回消息,完全不做更改:
return msg;
如果函数返回 null
,则不再传递任何消息,流程结束。
函数必须始终返回一个 msg 对象。返回一个数字或字符串将导致错误。
返回的消息对象不必与传入的对象相同;函数可以在返回之前构造一个全新的对象。例如:
var newMsg = { payload: msg.payload.length };
return newMsg;
msg.req
和 msg.res
属性。通常,Function 节点 应该 返回它们传递的消息对象,并对其属性进行任何更改。使用 node.warn() 在侧边栏中显示警告,以帮助您调试。例如:
node.warn("my var xyz = " + xyz);
有关更多详细信息,请参见下面的日志记录部分。
函数编辑对话框允许更改输出数量。如果有多个输出,函数可以返回一个消息数组,以发送到各个输出。
这使得编写一个根据某些条件将消息发送到不同输出的函数变得简单。例如,该函数将把主题为 banana
的任何内容发送到第二个输出而不是第一个:
if (msg.topic === "banana") {
return [ null, msg ];
} else {
return [ msg, null ];
}
以下示例将原始消息照原样传递到第一个输出,并将包含有效载荷长度的消息传递到第二个输出:
var newMsg = { payload: msg.payload.length };
return [msg, newMsg];
自 Node-RED 1.3 起
node.outputCount
包含为函数节点配置的输出数量。
这使得编写可以处理在编辑对话框中设置的可变数量的输出的通用函数成为可能。
例如,如果您希望在输出之间随机分配传入消息,您可以:
// 创建一个与输出数量相同长度的数组
const messages = new Array(node.outputCount)
// 选择随机输出编号以发送消息
const chosenOutputIndex = Math.floor(Math.random() * node.outputCount);
// 仅将消息发送到选定输出
messages[chosenOutputIndex] = msg;
// 返回包含所选输出的数组
return messages;
现在,您可以仅通过编辑对话框配置输出数量,而无需对函数本身进行更改。
函数可以通过在返回的数组中返回一个消息数组来在一个输出上返回多条消息。当为一个输出返回多条消息时,后续节点将逐个接收消息,按返回顺序处理。
在以下示例中,msg1
、msg2
、msg3
将发送到第一个输出。msg4
将发送到第二个输出。
var msg1 = { payload:"从输出 1 的第一条消息" };
var msg2 = { payload:"从输出 1 的第二条消息" };
var msg3 = { payload:"从输出 1 的第三条消息" };
var msg4 = { payload:"来自输出 2 的唯一消息" };
return [ [ msg1, msg2, msg3 ], msg4 ];
以下示例将接收到的有效载荷分割成单个单词,为每个单词返回一条消息。
var outputMsgs = [];
var words = msg.payload.split(" ");
for (var w in words) {
outputMsgs.push({payload:words[w]});
}
return [ outputMsgs ];
如果函数需要在发送消息之前执行异步操作,它无法在函数结束时返回消息。
相反,它必须使用 node.send()
函数,传入要发送的消息。它接受与上面描述相同的消息排列。
例如:
doSomeAsyncWork(msg, function(result) {
msg.payload = result;
node.send(msg);
});
return;
Function 节点会克隆您传递给 node.send
的每个消息对象,以确保没有意外修改在函数中重复使用的消息对象。在 Node-RED 1.0 之前,Function 节点不会克隆传递给 node.send
的 第一 条消息,但会克隆其余消息。
如果消息包含无法克隆的内容,或者出于性能原因以最小化发送消息的开销,Function 可以通过将 false
作为第二个参数传递给该函数,要求运行时 不克隆 传递给 node.send
的第一条消息:
node.send(msg,false);
自 Node-RED 1.0 起
如果 Function 节点对消息进行了异步操作,运行时将不会自动知道何时完成对消息的处理。
为了帮助其做到这一点,Function 节点应在适当的时候调用 node.done()
。这将允许运行时正确跟踪系统中的消息。
doSomeAsyncWork(msg, function(result) {
msg.payload = result;
node.send(msg);
node.done();
});
return;
自 Node-RED 1.1.0 起
随着 1.1.0 版本的发布,Function 节点提供了一个 On Start
选项卡(在 1.3.0 之前标记为 Setup
),您可以在其中提供每当节点启动时将运行的代码。这可用于设置 Function 节点所需的任何状态。
例如,它可以初始化主 Function 将使用的本地上下文中的值:
if (context.get("counter") === undefined) {
context.set("counter", 0)
}
在主 Function 开始处理消息之前,如果 On Start 函数需要完成异步工作,则可以返回一个 Promise。在 On Start 函数完成之前到达的任何消息将被排队,并在其准备好时处理。
如果您在函数中使用异步回调代码,则可能需要在流程重新部署时清理任何未完成的请求或关闭连接。您可以通过两种不同的方式做到这一点。
要么通过添加 close
事件处理程序:
node.on('close', function() {
// 在此清理任何异步代码 - 关闭连接等。
});
或者,自 Node-RED 1.1.0 起,您可以在节点的编辑对话框中向 On Stop
选项卡(以前标记为 Close
)添加代码。
如果节点需要记录某些内容到控制台,可以使用以下函数之一:
node.log("发生了一些事情");
node.warn("发生了一些您应该了解的事情");
node.error("哦,不,发生了一些坏事");
控制台输出出现的位置将取决于您的操作系统以及如何启动 Node-RED。如果您通过命令行启动 - 日志将出现在该控制台。如果您以系统服务的形式运行,则可能出现在系统日志中。如果您在像 PM2 这样的应用程序下运行,它将有自己的记录日志方式。在 Pi 上,安装脚本添加了一个 node-red-log
命令,可以显示日志。
warn
和 error
消息也发送到流程编辑器右侧的调试选项卡。
对于更细粒度的日志记录,node.trace()
和 node.debug()
也可用。
如果没有配置记录器捕获这些级别,则将看不到它们。
如果函数遇到应停止当前流程的错误,则应返回空值。要在同一选项卡上触发 Catch 节点,函数应调用 node.error
,并将原始消息作为第二个参数:
node.error("遇到错误", msg);
除了 msg
对象外,函数还可以在上下文存储中存储数据。
关于 Node-RED 中上下文的更多信息,请参见 这里。
在 Function 节点中,有三个预定义变量可用于访问上下文:
context
- 节点的本地上下文flow
- 流范围上下文global
- 全局范围上下文以下示例使用 flow
上下文,但同样适用于 context
和 global
。
访问上下文有两种模式;同步或异步。内置的上下文存储提供这两种模式。一些存储可能仅提供异步访问,并且如果以同步方式访问则会抛出错误。
要从上下文中获取值:
var myCount = flow.get("count");
要设置值:
flow.set("count", 123);
以下示例维护函数运行过的次数计数:
// 如果计数器不存在则将其初始化为 0
var count = context.get('count')||0;
count += 1;
// 将值存回
context.set('count',count);
// 使其成为输出 msg 对象的一部分
msg.count = count;
return msg;
自 Node-RED 0.19 起,也可以一次性获取或设置多个值:
// Node-RED 0.19 或更高版本
var values = flow.get(["count", "colour", "temperature"]);
// values[0] 是 'count' 值
// values[1] 是 'colour' 值
// values[2] 是 'temperature' 值
// Node-RED 0.19 或更高版本
flow.set(["count", "colour", "temperature"], [123, "red", "12.5"]);
在这种情况下,任何缺失的值都将设置为 null
。
如果上下文存储需要异步访问,则 get
和 set
函数需要额外的回调参数。
// 获取单个值
flow.get("count", function(err, myCount) { ... });
// 获取多个值
flow.get(["count", "colour"], function(err, count, colour) { ... })
// 设置单个值
flow.set("count", 123, function(err) { ... })
// 设置多个值
flow.set(["count", "colour"], [123, "red"], function(err) { ... })
传递给回调的第一个参数 err
仅在访问上下文时发生错误时设置。
计数示例的异步版本变为:
context.get('count', function(err, count) {
if (err) {
node.error(err, msg);
} else {
// 如果计数器不存在则将其初始化为 0
count = count || 0;
count += 1;
// 将值存回
context.set('count',count, function(err) {
if (err) {
node.error(err, msg);
} else {
// 使其成为输出 msg 对象的一部分
msg.count = count;
// 发送消息
node.send(msg);
}
});
}
});
自 0.19 起,可以配置多个上下文存储。例如,可以使用 memory
和 file
基于的存储。
get
/set
上下文函数接受一个可选参数以识别要使用的存储。
// 获取值 - 同步
var myCount = flow.get("count", storeName);
// 获取值 - 异步
flow.get("count", storeName, function(err, myCount) { ... });
// 设置值 - 同步
flow.set("count", 123, storeName);
// 设置值 - 异步
flow.set("count", 123, storeName, function(err) { ... })
全局上下文可以在 Node-RED 启动时预填充对象。这在主 settings.js 文件中的 functionGlobalContext
属性下定义。
这可用于在 Function 节点中 加载附加模块。
函数节点也可以像其他节点一样提供自己的状态装饰。要设置状态,请调用 node.status
函数。例如
node.status({fill:"red",shape:"ring",text:"未连接"});
node.status({fill:"green",shape:"dot",text:"已连接"});
node.status({text:"仅文本状态"});
node.status({}); // 清除状态
有关接受参数的详细信息,请参见 节点状态文档
任何状态更新也可以被状态节点捕获。
functionGlobalContext
选项无法直接在 Function 节点中加载附加节点模块。它们必须在您的 settings.js 文件中加载,并添加到 functionGlobalContext
属性中。
例如,可以通过在 settings.js 文件中添加以下内容,将内置的 os
模块提供给所有函数。
functionGlobalContext: {
osModule:require('os')
}
这时,可以在函数中引用该模块,如 global.get('osModule')
。
从设置文件加载的模块必须安装在与设置文件相同的目录中。对于大多数用户,这将是默认用户目录 - ~/.node-red
:
cd ~/.node-red
npm install name_of_3rd_party_module
functionExternalModules
选项自 Node-RED 1.3.0 起
通过在您的 settings.js 文件中将 functionExternalModules
设置为 true
,Function 节点的编辑对话框将提供一个列表,您可以在其中添加应该在节点中可用的附加模块。您还可以指定将在节点代码中用于引用该模块的变量。
模块在节点部署时会自动安装到 ~/.node-red/node_modules/
中。
自 Node-RED 3.1.0 起
可以在设置选项卡上为函数节点设置超时。该值(以秒为单位)是运行时将在引发错误之前允许 Function 节点运行的时间。如果设置为 0,默认情况下,则不应用超时。
在 Function 节点中可以使用以下对象。
node
node.id
: Function 节点的 ID - 自 0.19 起添加node.name
: Function 节点的名称 - 自 0.19 起添加node.outputCount
: 设置的 Function 节点的输出数量 - 自 1.3 起添加node.log(..)
: 记录一条消息node.warn(..)
: 记录一条警告消息node.error(..)
: 记录一条错误消息node.debug(..)
: 记录一条调试消息node.trace(..)
: 记录一条跟踪消息node.on(..)
: 注册事件处理程序node.status(..)
: 更新节点状态node.send(..)
: 发送一条消息node.done(..)
: 以消息结束context
context.get(..)
: 获取节点范围的上下文属性context.set(..)
: 设置节点范围的上下文属性context.keys(..)
: 返回所有节点范围上下文属性键的列表context.flow
: 与 flow
相同context.global
: 与 global
相同flow
flow.get(..)
: 获取流范围的上下文属性flow.set(..)
: 设置流范围的上下文属性flow.keys(..)
: 返回所有流范围上下文属性键的列表global
global.get(..)
: 获取全局范围的上下文属性global.set(..)
: 设置全局范围的上下文属性global.keys(..)
: 返回所有全局范围上下文属性键的列表RED
RED.util.cloneMessage(..)
: 安全克隆消息对象,以便可以重复使用env
env.get(..)
: 获取环境变量Function 节点还提供以下模块和函数可用:
Buffer
- Node.js Buffer
模块console
- Node.js console
模块(node.log
是 preferred 记录方式)util
- Node.js util
模块setTimeout/clearTimeout
- JavaScript 超时函数。setInterval/clearInterval
- JavaScript 间隔函数。注意:每当 Function 节点被停止或重新部署时,它会自动清除任何未完成的超时或间隔定时器。
版权所有 OpenJS Foundation 和 Node-RED 贡献者。保留所有权利。OpenJS Foundation 拥有并使用注册商标。有关 OpenJS Foundation 的商标列表,请参阅我们的 商标政策 和 商标列表。未在 OpenJS Foundation 商标列表 中列出的商标和徽标是其各自持有者的商标™或注册商标®。使用它们并不意味着与它们有任何关联或认可。
OpenJS Foundation | 使用条款 | 隐私政策 | OpenJS Foundation 章程 | 商标政策 | 商标列表 | Cookie 政策