As previously discussed in the the understanding the message object tutorial messages are passed between nodes using a message object.
Because of this the node-red documentation advised against reusing the msg object but instead recommended creating a new msg object and or cloning the msg object.
Node-Red will automatically clone message objects under certain circumstances, and this behaviour has changed in node-red 1.0 and is described in this tutorial from the Node-Red creator.
In this tutorial I want to look at the message storage objects like flow and global as you encounter similar problems here and you need to be aware of them.
Below is a very simple flow that creates a drop down list from a list stored in a global array.
It uses a change node to get the global object which is passed to a function node that adds an element to the top of the list.
The flow is taken from a database application that I’m developing.
The list in the global object initially looks like this:
If I click on the inject node to add the none element to the list and look at the UI I see it displayed on the screen like this.
All good it seems to work. However if I look again at the stored global object I see :
You can see it has been added to the global object, but I didn’t do it. You should notice there is no set command used in the function node.
var options=msg.options; var res=options.unshift("NONE"); msg.options=options; return msg;
Now if I click on the inject node again I get NONE twice and it I click again I get it three times etc.
This is not what I wanted. So what is happening?
The msg.options is set to the global.producer_codes in the change node and passed into the function node.
The function node receives the msg.options and adds the NONE element to it.
However because the change node actually creates a pointer(reference) to global.producer_codes when I update the msg,options I am actually updating the global.producer_codes.
In order to make this work correctly I need to separate the global.producer_codes from msg.options.
This I do by cloning the msg.options object so our function node now looks like this.
var options=RED.util.cloneMessage(msg.options); var res=options.unshift("NONE"); msg.options=options; return msg;
Notice the use of the Node-red utility function . RED.util.cloneMessage
- Understanding the Node-Red Message Object
- Using the Node-Red Function Node.
- Storing Data in Node-Red Variables