Context variables

Hi, guys

Just come across something strange. Could anyone give me some guides? Thanks heaps your time in advance.

Problem: I set two flow variables. When I assign value to one of the variables, another one get the same value assigned.

This text will be hidden

I use function: change data format to create flow variable: dataFromFirebaseFormated. Then I use dataFromFirebaseFormated to create another flow variable: sensorData. When I use function: store data to store data to variable: sensorData, the same value is stored at variable: dataFromFirebaseFormated. Show as annotation below

function: change data format

// data of card-allocation from firebase
let dataFromFirebase = JSON.parse(msg.payload);

let dataFromFirebaseFormated = flow.get('dataFromFirebaseFormated') || [];

// 1. take each value from variable dataFromFirebase
for (let x in dataFromFirebase) {
    dataFromFirebaseFormated.push(dataFromFirebase[x]);
}

// 2. change format of mac from 'F09AC0BBA5E8' to [ 'F0', '9A', 'C0', 'BB', 'A5', 'E8' ]
dataFromFirebaseFormated.forEach(function(value) {
    value.mac = value.mac.match(/.{1,2}/g);
});

// 3. change format of mac from [ 'F0', '9A', 'C0', 'BB', 'A5', 'E8' ] to [240, 154, 192, 187, 165, 232]
dataFromFirebaseFormated.forEach(function(value) {
    value.mac.forEach(function(value2, index) {
        value.mac[index] = parseInt(value2, 16);
        value.anchor = [];
        value.presence = [];
        value.panic = 0;
        value.date = 0;
    });
});

flow.set('dataFromFirebaseFormated', dataFromFirebaseFormated);

msg.payload = dataFromFirebaseFormated;

return msg;

function: store data

// data of card-allocation from firebase
let dataFromFirebase = JSON.parse(msg.payload);

let dataFromFirebaseFormated = flow.get('dataFromFirebaseFormated') || [];

// 1. take each value from variable dataFromFirebase
for (let x in dataFromFirebase) {
    dataFromFirebaseFormated.push(dataFromFirebase[x]);
}

// 2. change format of mac from 'F09AC0BBA5E8' to [ 'F0', '9A', 'C0', 'BB', 'A5', 'E8' ]
dataFromFirebaseFormated.forEach(function(value) {
    value.mac = value.mac.match(/.{1,2}/g);
});

// 3. change format of mac from [ 'F0', '9A', 'C0', 'BB', 'A5', 'E8' ] to [240, 154, 192, 187, 165, 232]
dataFromFirebaseFormated.forEach(function(value) {
    value.mac.forEach(function(value2, index) {
        value.mac[index] = parseInt(value2, 16);
        value.anchor = [];
        value.presence = [];
        value.panic = 0;
        value.date = 0;
    });
});

flow.set('dataFromFirebaseFormated', dataFromFirebaseFormated);

msg.payload = dataFromFirebaseFormated;

return msg;

node info:
18 Feb 23:21:20 - [info] Node-RED version: v1.0.3
18 Feb 23:21:20 - [info] Node.js version: v10.19.0

I haven't had time to look in detail at your code but I imagine this is caused by the fact that in javascript objects are referred to by reference rather than by value. So if you save an object in the context you are actually just saving a pointer to that object not the object itself. Then if you save the same object in another variable in context it will save another pointer to the same object. So if you then change the object it will appear to have changed in both places. The solution is to make a copy of the object before saving it. You can do that using RED.util.cloneMessage(..). So maybe in store data you might do something like

let dataFromFirebaseFormated = RED.util.cloneMessage(flow.get('dataFromFirebaseFormated') || []);

Though having said that I am not certain that cloneMessage will work with an array, there may be a better way to make a copy of an array. Try it and see.

The problem was indeed caused by reference mechanism.

Thanks so much!!!

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