Function with 2 outputs... simply think that I don't understand

Hi there all,
I have this simply function node:

With this code inside:

msg.payload ='payload';
msg.topic   = 'topic'

msg2 = msg;

msg2.payload ='payload2';
msg2.topic   = 'topic2';
//
return [msg, msg2];

Now I expect to have different output...
But I don't understand why I take same output on all 2 debug nodes:
image

I know it's some basic thinks... but anyone can explain me why please ?
Thanks a lot
Denis

That is because of the way javascript handles objects. When you write msg2 = msg all you are doing is creating another Reference (or pointer) to the object that msg refers to. So when you change the contents of the object that msg refers to then since msg2 refers to the same object it also changes. If you want to make a new object with the same contents as msg you have to clone it, which you can do using
msg2 = RED.util.cloneMessage(msg)

1 Like

Also make sure to use two outputs on the function node

[{"id":"4307c3e9.c7655c","type":"debug","z":"42d0712.0c3a21","name":"d1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":560,"y":60,"wires":[]},{"id":"b14cafea.886098","type":"debug","z":"42d0712.0c3a21","name":"d2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":140,"wires":[]},{"id":"b2cc93a7.a83778","type":"inject","z":"42d0712.0c3a21","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":120,"wires":[["dbc34ba4.17d458"]]},{"id":"dbc34ba4.17d458","type":"function","z":"42d0712.0c3a21","name":"","func":"msg.payload ='payload';\nmsg.topic   = 'topic'\n\nmsg2 = RED.util.cloneMessage(msg)\n\nmsg2.payload ='payload2';\nmsg2.topic   = 'topic2';\n//\nreturn [msg, msg2];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":410,"y":120,"wires":[["4307c3e9.c7655c"],["b14cafea.886098"]]}]
1 Like

You could alternatively use Object.assign...

msg.payload ='payload';
msg.topic   = 'topic'

msg1 = Object.assign({}, msg);
msg2 = msg;

msg2.payload ='payload2';
msg2.topic   = 'topic2';
//
return [msg1, msg2];
[{"id":"f8bb35e4.ae0038","type":"inject","z":"c9c4eeb8.bad8e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":2280,"wires":[["82cdef83.e8b54"]]},{"id":"ad5eb769.75d0a8","type":"debug","z":"c9c4eeb8.bad8e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":570,"y":2250,"wires":[]},{"id":"82cdef83.e8b54","type":"function","z":"c9c4eeb8.bad8e","name":"","func":"msg.payload ='payload';\nmsg.topic   = 'topic'\n\nmsg1 = Object.assign({}, msg);\n\nmsg2 = msg;\n\nmsg2.payload ='payload2';\nmsg2.topic   = 'topic2';\n//\nreturn [msg1, msg2];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":370,"y":2280,"wires":[["ad5eb769.75d0a8"],["2a82a40a.f9536c"]]},{"id":"2a82a40a.f9536c","type":"debug","z":"c9c4eeb8.bad8e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":574.765625,"y":2315,"wires":[]}]
1 Like

TBH, unless there is other stuff in the original msg the OP wants to carry over to msg2 it'd be better (and faster) to simply create a new object...

msg.payload ='payload';
msg.topic  = 'topic';
var msg2 = {
  payload: "payload2",
  topic: "topic2"
}
return [msg, msg2];

BUT if the OP did want to clone the original, it is recommended to use RED.util.cloneMessage() (for reasons I forget right now)

msg.payload = 'payload';
msg.topic  = 'topic';
var msg2 = RED.util.cloneMessage(msg);
msg2.payload = "payload2";
msg2.topic = "topic2";
return [msg, msg2];
2 Likes

A lot of answers... thanks all so much.
I arrive from Cobol, so there if I MOVE an object to another, there is physically a move of all bytes
to the other object (01 level).

Anyway... I just make a test with the normal vars "move" ... and in this case it's a normal move,
and not only a virtual pointer to the same var.

Normally what I need is to make more outputs with same object msg,
but with changed msg.ip in order to make more "cast node" for Google Home
to work with the same alarm message in the same time.

So I solved in this mode:

msg_garage = RED.util.cloneMessage(msg); // funziona solo clonando l'oggetto 
msg_cucina = RED.util.cloneMessage(msg); // altrimenti fa rif. allo stesso
msg_altro  = RED.util.cloneMessage(msg); 
//
msg_cucina.ip = '192.168.1.212'; //cucina
msg_garage.ip = '192.168.1.161'; //garage
msg_altro.ip  = '192.168.1.184';  //altro
//
return [msg_garage, msg_cucina, msg_altro];
//

The changed IP is work now... but the "cast node" give me an error...
"Not able to get media file via google-tts:get key failed from google"

I'll do a search to understand why...
I learned a new think today :slight_smile:
Again thanks a lot all for the help.
Denis

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.