Best way of adding a value to global context array of objects

I have an array of objects (one property is the hostname of the device) stored in my global context.
Now I would like to ping some of them and store the value of roundtrip in ms to it's to the related object.
What is the best solution to do so?

I read a lot about .map() and .forEach() and the fact that I don't need to recreate the whole context array, but just add that property to an object in the array confuses me on how to do it best.
Moreover, I am a bit worried about doing that every let's say 60s on my rpi4.

Is it safe to just itter over the array with an for loop and add that property where the hostname matches?

let hosts = global.get('hosts');
for (let i = 0; i < hosts.length; i++) {
    var e = hosts[i];
    if(e.host === msg.topic){
        global.set('hosts['+i+'].ping', msg.payload)
    }
}

Assuming you did a

const hosts = global.get("hosts")

at the beginning of your script, this

doesn't work. It is as easy as

e.ping = msg.payload

to put the new ping value back in the object.

Why? const hosts = global.get("hosts") puts a reference to the array stored in global context into hosts. e already is the array element you intend to update & again a reference. Thus you're directly updating the object stored in the array stored in global context. This is quite elegant - as long as you're aware what you're doing.

Something like:

const hosts = global.get('hosts') || [];
let changed = false;

const newHosts = hosts.map((h) => {
  if (h.host !== msg.topic) return;
  h.ping = msg.payload;
  changed = true;
});

if (changed) global.set('hosts', newHosts);

Whether you use a for loop or map method, in both cases you create a variable

That is indeed very elegant. I read a lot about those references but knowing where they happen seams like mysterious magic knowledge to me.

this actually works.
But as you say, it's somehow not elegant at all…

:+1: You're absolutely right; it does.
That's the beauty of Node-RED; full of great user-friendly functionality... !

Wouldn't this be simpler if your global context was an object (the key is the hostname of the device) instead of an array?

let hosts = global.get'hosts') || {}
hosts[msg.topic].ping = msg.payload
global.set ('hosts', hosts}

jbudd, but would be simpler to use a change node, and no code required at all.

@novski You could also add the host name to the object and return an array of objects if an array is required.

[{"id":"e44b7242b3d23e14","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"192.168.1.24","payload":"24","payloadType":"num","x":480,"y":2760,"wires":[["dce3b25a146989d2"]]},{"id":"dce3b25a146989d2","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"host[msg.topic].ping","pt":"flow","to":"payload","tot":"msg"},{"t":"set","p":"host[msg.topic].host","pt":"flow","to":"topic","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[$flowContext(\"host\").*]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":2840,"wires":[["fcb4735590df7d69"]]},{"id":"fcb4735590df7d69","type":"debug","z":"d1395164b4eec73e","name":"debug 2461","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":2840,"wires":[]}]

My global.hosts is not an object but an array.

Yes we know that, we are pointing out that if you set it as an object it would be simple to add/alter it, and you can still pull an array of objects from it, if you also require an array for other things.

It's the incoming message that stores it as an array.
It does not make sense to rearrange it every time it gets written as it is the fritzbox node that querries my dhcp active leases.

That is not what we are suggesting. The suggestion is to store it all the time as an object as this is easier to write to with out searching as to what array element to write to. It is only a suggestion you may do as you want.

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