Function节点允许JavaScript代码针对传入的消息运行,然后返回零个或者多个消息以继续流。
消息以一个称为msg的对象的形式进行传输。按照约定msg有一个属性msg.payload包含了消息的主体(也就是消息的具体内容)。
其他的节点可以把它们自己的属性附加到消息中,并且他们应该在自己的记录中被描述。
写进Function节点的代码代表了功能的主体。最简单的功能就是返回消息,比如下面这样:
return msg
如果功能返回的是null,那么将不会有消息在流中传递。
返回的消息对象不必要和一开始传输的对象一样,功能中可以构建一个完全全新的对象在返回消息对象之前。比如:
var newMsg = {payload:msg.payload.length};
return newMsg;
注:构建一个新的消息对象将失去任何一个已经接收到的消息的消息属性。这可能会破坏一些流,比如HTTP/Respone流需要msg.req和msg.res属性被保存到端到端。通常,Function节点应该返回已经传输的对它们的属性做了任何改变消息对象
编辑对话的功能允许输出的数量发生改变。如果不只有一个输出,通过发送给多个输出这个功能可以返回一个数组的信息。
这使得写一个取决于一些情况的发送信息给多个不同输出的功能很容易。比如,这个功能将发送任何基于主题banana给第二个输出而不是第一个。
If(msg.topic === ‘banana’){
return [null,msg];
}else{
return [msg, null];
}
接下来的例子传输了原始的输出在第一个输出并且一个包含了内容的长度的消息被传输到了第二个输出口;
var newMsg = { payload: msg.payload.length};
return [msg, newMsg];
通过在返回的数组中能够返回一组消息,函数可以在输出上返回多条消息。当一个输出口返回多个消息时,后续节点将按照他们返回的循序一次接收一条消息。
在下面的例子中,msg1,msg2,msg3将被发送给第一个输出口。msg4将被发送给第二个输出口。
var msg1 = {payload:”first out of output 1”};
;var msg2 = {payload:”second out of output 1”};
var msg3 = {payload:”third out of output 1”};
var msg4 = {payload:”only message from output 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){
node.send({payload:result});
});
return;
如果您在函数中使用异步回调代码,那么无论何时重新部署流,您都可能需要清理所有未完成的请求,或者关闭任何连接。您可以通过添加任何关闭事件处理程序来完成操作。
node.on(“close”, function(){
//tidy up any sync code here – shutdown connections and so on.
})
如果一个节点需要在控制台上打印一些东西,你可使用如下的功能
node.log(“something happened”);
node.warn(“something happened you should know about”);
node.error(“oh no, something bad happended”);
warn和error消息同时会被发送到流的debug栏。
如果函数遇到应该暂停当前流的错误,则它不应该返回任何内容。 要在同一个选项卡上触发Catch节点,函数应该使用原始消息作为第二个参数调用node.error:
node.error("hit an error",msg);
除了msg对象之外,函数还可以在其上下文对象中的调用之间存储数据。
下面的例子保持了一个关于的方法运行次数的值。
// initialise the counter to 0 if it doesn't exist already
var count = context.get('count')||0;
count += 1;
// store the value back
context.set('count',count);
// make it part of the outgoing msg object
msg.count = count;
默认情况下,上下文数据在Node-RED的重新启动之间不会持久。
注意:在Node-RED v0.13之前,文档中使用上下文的方式是直接访问它:var count = context.count;该方法仍然受支持,但不推荐使用context.get / context.set函数。 这是为了能够在未来版本中保留上下文数据。
在Node-RED 0.13或更高版本中,就像上下文对象是本地节点一样,还有一个流级上下文,它由给定选项卡上的所有节点(不仅仅是函数节点)共享。 它通过流对象访问:
var count = flow.get('count')||0;
还有一个全局上下文可供所有节点共享并可供所有节点访问。 例如,要在整个画布中使变量foo全局可用:
global.set("foo","bar");
// this is now available to other nodes
然后可以使用通过.get方法。
var myfoo = global.get("foo");
// this should now be "bar"
当Node-RED启动时,全局上下文也可以预先填入对象。 这是在functionGlobalContext属性下的主settings.js文件中定义的。
例如,内置的os模块可用于所有功能:
functionGlobalContext:{osModule:require('os')}
在这一点上,模块可以在一个函数内被引用
global.get('osModule').
功能节点也可以像其他节点一样提供自己的状态装饰。 要设置状态,请调用node.status函数。 例如
node.status({fill:"red",shape:"ring",text:"disconnected"});
node.status({fill:"green",shape:"dot",text:"connected"});
node.status({text:"Just text status"});
node.status({});
// to clear the status
更多参数细节可以看https://nodered.org/docs/creating-nodes/status.
任何状态的更新都可以被状态节点捕捉到。
功能节点还提供以下模块和功能:0
Buffer模块
Console模块
Util模块
setTimeout/clearTimeout功能
setInterval/clearInterval功能