Multiple outputs of function node not working

I've read my notes on how to construct nodes with multiple outputs, but it isn't working.

The idea is that the input cycles from 0 to 3 (numbers).
Depending on its value, depends which output is sent a 1.
All values are set to 0 at the beginning and depending on the payload's value, it sets that message's value to 1.

Ok, the number of = signs may be a problem, but I did it with only two and got the same results.

I am getting a lot of undefined from the node.warn( )
Yet, they are defined at the top.

So I'm missing something.

Sorry but I can't nut it out.

var msg1 = 0;
var msg2 = 0;
var msg3 = 0;
var msg4 = 0;
msg.payload = parseInt(msg.payload);
node.warn("message payload is " + msg.payload);
if (msg.payload === 0)
{
    //
    msg1.payload = 1;
} else
if (msg.payload === 1)
{
    //
    msg2.payload = 1;
} else
if (msg.payload === 2)
{
    //
    msg3.payload = 1;
} else
if (msg.payload === 3)
{
    //
    msg4.payload = 1;
}
node.warn("--------");
node.warn(msg1.payload);
node.warn(msg2.payload);
node.warn(msg3.payload);
node.warn(msg4.payload);
return [msg1, msg2, msg3, msg4];

You get undefined because you don't define msgx.payload but msgx = 0.

try this instead:

[{"id":"588e975f.2bf15","type":"inject","z":"681f8bde.8887bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":450,"wires":[["541beb20.ef86e4"]]},{"id":"541beb20.ef86e4","type":"function","z":"681f8bde.8887bc","name":"","func":"a =2\np = parseInt(msg.payload);\nnode.warn(\"message payload is \" + msg.payload);\n\nout = []\n\nfor(x=0;x<4;x++){\n\t\n\tif(x==a){\n\t\tout.push({payload:p,output:x})\n\t}\n\telse{\n\t\tout.push({payload:null,output:x})\n\n\t}\n}\n\nreturn out","outputs":4,"noerr":0,"x":300,"y":450,"wires":[["f7603811.8dce98"],["87bd304.4a77fd"],["1a51dec4.023271"],["6ce0f346.c1b394"]]},{"id":"f7603811.8dce98","type":"debug","z":"681f8bde.8887bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":475,"y":375,"wires":[]},{"id":"87bd304.4a77fd","type":"debug","z":"681f8bde.8887bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":475,"y":425,"wires":[]},{"id":"1a51dec4.023271","type":"debug","z":"681f8bde.8887bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":475,"y":475,"wires":[]},{"id":"6ce0f346.c1b394","type":"debug","z":"681f8bde.8887bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":475,"y":525,"wires":[]}]

Change to

var msg1 = {}; 
var msg2 = {}; 
var msg3 = {}; 
var msg4 = {};

That would still end up as undefined depending on the test.

Agreed but if one of his tests do pass he'll get an error trying to set/access a property of a non object.

Bakman2

I am not getting (understanding) the code in the function node.

I thought (yes: dangerous) that you had to assign variable names.

So, how does:

a =2
p = parseInt(msg.payload);

work?

Shouldn't it be:

var a = 2;
var p = parseInt(msg.payload);

Depending if ....

p = parseInt(msg.payload);
if (p == 0)
{
    set msg1 to 1
}

and so on.

It could be var or let or even const if they don't get changed, but I'm lazy and it works too.

msg.payload is a timestamp and which never be 0 or 1 so that test will fail = no output.
my example is a bad example :wink: that is why i introduced the a, you can replace it ofcourse.

Fair enough.

I can't use const as they are all set to 0 at the start.
Depending on the value the appropriate msgx is set to 1.

Um.... Sorry. I get that you introduced the variable a, but I am not seeing how that fits in to the workings.

If you're only wanting to fire a single output, I'd do it like this...

var p = parseInt(msg.payload);
if (p === 0) {
  return [msg, null, null, null];
} else if (p === 1) {
  return [null, msg, null, null];
} else if (p === 2){
  return [null, null, msg, null];
} else if (p === 3) {
    return [null, null, null, msg];
};


but in this case, you could simply use a switch node with 4 == checks

Thanks Steve.

Close.

The output is only a 1. Not the actual value.
The flow is a bit academic as I am using it to test another part.
This is basically hardware simulation.
The outputs 0 and 1 are basically off and on.
But I get what you wrote.
So I could change that code to something like:

var p = parseInt(msg.payload);
if (p === 0) {
  return [1,0,0,0l];
} else if (p === 1) {
  return [0,1,0,0];
} else if (p === 2){
  return [0,0,1,0];
} else if (p === 3) {
    return [0,0,0,1];
};

Sure.

I just got confused when I tried to use variables rather than how you did it.

Shall apply your suggestion.

Thanks.

Oh, quickie:
Why the

p = parsInt(msg.payload)

line?

Wouldn't the line I had work?

msg.payload = parseInt(msg.payload);

That won't work. You MUST return an object...

var p = parseInt(msg.payload);
msg.payload = 1;
if (p === 0) {
  return [msg, null, null, null];
} else if (p === 1) {
  return [null, msg, null, null];
} else if (p === 2){
  return [null, null, msg, null];
} else if (p === 3) {
    return [null, null, null, msg];
};

Will send 1 in payload

So that is more readable and portable and also, as you need to assign 1 to msg.payload before returning.

1 Like

The key for multiple outputs is to remember that you need to create an object {"payload":"z"} for each output.

Ok. but as I think I wrote the code - the first one - msg1, msg2, msg3, and msg4 are sent back.
msg.payload isn't sent back.

So.....

as I have to send a 0 and 1 on all outputs.

It would be something like:

var p = parseInt(msg.payload);
msg.payload = 1;
msg1.payload = 0;
if (p ===0)
{
  return [msg, msg1,msg1,msg1];
} else
if (p ===1)
{
  return [msg1,msg,msg1,msg1];
} else
if (p===2)
{
  return [msg1,msg1,msg,msg1];
} else
if (p===3)
{
  return [msg1,msg1,msg1,msg];
}

It's an assumption on my behalf that the OP doesn't want the outputs to fire if the condition is not met.

If he does, it could be simplified to 1 line...

return [ {payload : msg.payload == 0 ? 1 : 0}, {payload : msg.payload == 1 ? 1 : 0}, {payload : msg.payload == 2 ? 1 : 0}, {payload : msg.payload == 3 ? 1 : 0}];

What are you trying to accomplish, it sounds like something a switch node could do though

@Trying_to_learn try this ^

Exactly what I said. But OP says it's academic :man_shrugging:

1 Like

Um...

No, there are 4 outputs.
The state of them can only be 0 or 1.

This code seems to work:

var msg1 = {};
var p = parseInt(msg.payload);
msg.payload = 1;
msg1.payload = 0;
if (p ===0)
{
  return [msg, msg1,msg1,msg1];
} else
if (p ===1)
{
  return [msg1,msg,msg1,msg1];
} else
if (p===2)
{
  return [msg1,msg1,msg,msg1];
} else
if (p===3)
{
  return [msg1,msg1,msg1,msg];
}

Just now asking about the else parts.

If the condition is tested:

if (p === *x*)
{
   ....

Ah!

Ok, got it.

As I can't return values, I have to return msgx's.....

I need to have the separate return lines.
Depending on which one I want to set as 1.

For your code from the first post to work you only need a small change. We can deliver you all kinds of alternative ways to do this, but I feel the understanding on how to get your original code to work might be better.

A couple things to remember: messages returned are objects, and the data you access in it are stored in the payload property, that’s why you access those through msg.payload. In order to put together your own messages to return, you need to make objects with a payload property on them, which you can edit in your if statement.

You create an object by stating
var test_message = {};
You add properties to an object by stating
test_message.payload = 0;
However, if that property is added within an if statement, it won’t exist in the else clause, thus if you try to log it later on it is still undefined.
To add properties to an object at creation time, so they are initialised when logging or returning, the following works:
var test_message = { payload: 0}, or when you prefer it on multiple lines for readability:

var test_message = {
    payload: 0
}

So, to fix the code in your initial post, replace the first four lines that create your four messages by object initialisations with a payload property present:

var msg1 = { payload: 0}; 
var msg2 = { payload: 0}; 
var msg3 = { payload: 0}; 
var msg4 = { payload: 0}; 

Edit: sorry my phone wrangled the original code while quoting I’ll try fo fix the line endings