1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add node.send/on to Function node

This commit is contained in:
Nick O'Leary 2015-03-17 13:40:12 +00:00
parent a1dac1e290
commit dd4cec84bf
3 changed files with 72 additions and 35 deletions

View File

@ -39,15 +39,21 @@
<p>The message is passed in as a JavaScript object called <code>msg</code>.</p>
<p>By convention it will have a <code>msg.payload</code> property containing
the body of the message.</p>
<p>If your node need to log anything use the <code>node</code> object:
<h4>Logging and Error Handling</h4>
<p>To log any information, or report an error, the following functions are available:</p>
<ul>
<li>Info: <code>node.log(msg);</code></li>
<li>Warning: <code>node.warn(msg);</code></li>
<li>Error: <code>node.error(msg);</code></li>
<li><code>node.log("Log")</code></li>
<li><code>node.warn("Warning")</code></li>
<li><code>node.error("Error")</code></li>
</ul>
</p>
<p>The function should return the messages it wants to pass on to the next nodes
in the flow. It can return:</p>
<p>The Catch node can also be used to handle errors. To invoke a Catch node,
pass <code>msg</code> as a second argument to <code>node.error</code>:</p>
<pre>node.error("Error",msg)</pre>
<h4>Sending messages</h4>
<p>The function can either return the messages it wants to pass on to the next nodes
in the flow, or can call <code>node.send(messages)</code>.</p>
<p>It can return/send:</p>
<ul>
<li>a single message object - passed to nodes connected to the first output</li>
<li>an array of message objects - passed to nodes connected to the corresponding outputs</li>

View File

@ -19,19 +19,57 @@ module.exports = function(RED) {
var util = require("util");
var vm = require("vm");
function sendResults(node,_msgid,msgs) {
if (msgs == null) {
return;
} else if (!util.isArray(msgs)) {
msgs = [msgs];
}
var msgCount = 0;
for (var m=0;m<msgs.length;m++) {
if (msgs[m]) {
if (util.isArray(msgs[m])) {
for (var n=0; n < msgs[m].length; n++) {
msgs[m][n]._msgid = _msgid;
msgCount++;
}
} else {
msgs[m]._msgid = _msgid;
msgCount++;
}
}
}
if (msgCount>0) {
node.send(msgs);
}
}
function FunctionNode(n) {
RED.nodes.createNode(this,n);
var node = this;
this.name = n.name;
this.func = n.func;
var functionText = "var results = null; results = (function(msg){\n"+this.func+"\n})(msg);";
var functionText = "var results = null;"+
"results = (function(msg){ "+
"var __msgid__ = msg._msgid;"+
"var node = {"+
"log:__node__.log,"+
"error:__node__.error,"+
"warn:__node__.warn,"+
"on:__node__.on,"+
"send:function(msgs){ __node__.send(__msgid__,msgs);}"+
"};\n"+
this.func+"\n"+
"})(msg);";
this.topic = n.topic;
var sandbox = {
console:console,
util:util,
Buffer:Buffer,
node: {
log : function() {
__node__: {
log: function() {
node.log.apply(node, arguments);
},
error: function(){
@ -39,11 +77,18 @@ module.exports = function(RED) {
},
warn: function() {
node.warn.apply(node, arguments);
},
send: function(id,msgs) {
sendResults(node,id,msgs);
},
on: function() {
node.on.apply(node,arguments);
}
},
context: {
global:RED.settings.functionGlobalContext || {}
}
},
setTimeout: setTimeout
};
var context = vm.createContext(sandbox);
try {
@ -53,26 +98,8 @@ module.exports = function(RED) {
var start = process.hrtime();
context.msg = msg;
this.script.runInContext(context);
var results = context.results;
if (results == null) {
results = [];
} else if (results.length == null) {
results = [results];
}
if (msg._topic) {
for (var m in results) {
if (results[m]) {
if (util.isArray(results[m])) {
for (var n=0; n < results[m].length; n++) {
results[m][n]._topic = msg._topic;
}
} else {
results[m]._topic = msg._topic;
}
}
}
}
this.send(results);
sendResults(this,msg._msgid,context.results);
var duration = process.hrtime(start);
var converted = Math.floor((duration[0]* 1e9 + duration[1])/10000)/100;
this.metric("duration", msg, converted);

View File

@ -105,13 +105,17 @@ describe('function node', function() {
var count = 0;
n2.on("input", function(msg) {
count++;
should(msg).have.property('payload', count);
should(msg).have.property('_topic', 'baz');
if (count == 2) {
done();
try {
should(msg).have.property('payload', count);
should(msg).have.property('_msgid', 1234);
if (count == 2) {
done();
}
} catch(err) {
done(err);
}
});
n1.receive({payload:"foo", topic: "bar", _topic:"baz"});
n1.receive({payload:"foo", topic: "bar",_msgid:1234});
});
});