Your way...
Here is how you can get the global values using async...
Demo flow
[{"id":"cb6e0ab3e1d7dfac","type":"inject","z":"f888b812e6b0fc73","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1220,"y":160,"wires":[["8e3c82ae3f720444"]]},{"id":"8e3c82ae3f720444","type":"function","z":"f888b812e6b0fc73","name":"async get","func":"\n/**\n * Set a value in context\n * @param {'global'|'flow'|'context'} scope - The name of the scope\n * @param {string} key - The key name to store against\n * @param {any} val - The value to store in context\n * @param {string} [store] - The name of the context store\n */\nlet asyncSetContext = (scope, key, val, store) => {\n const theScope = globalThis[scope]\n return new Promise((resolve, reject) => {\n theScope.set(key, val, store, (error) => {\n if (error) {\n reject(error)\n } else {\n resolve()\n }\n })\n })\n}\n\n/**\n * Get a value from context\n * @param {'global'|'flow'|'context'} scope - The name of the scope\n * @param {string} key - The key name to get\n * @param {string} [store] - The name of the context store\n */\nlet asyncGetContext = (scope, key, store) => {\n const theScope = globalThis[scope]\n return new Promise((resolve, reject) => {\n theScope.get(key, store, (error, value) => {\n if (error) {\n reject(error)\n } else {\n resolve(value)\n }\n })\n })\n}\n\n\nconst myGlobalVar = await asyncGetContext('global', 'myGlobalVar', 'persistent')\nconst myFlowVar = await asyncGetContext('flow', 'myFlowVar', 'memory')\nmsg.payload = {\n myGlobalVar,\n myFlowVar\n}\nawait asyncSetContext('global', 'myNewGlobalVar', msg.payload, 'persistent')\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1370,"y":160,"wires":[["21709d0c4e5a472c"]]},{"id":"7a12c01d8aa694fc","type":"inject","z":"f888b812e6b0fc73","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1220,"y":100,"wires":[["bd71ffd46b07639f"]]},{"id":"bd71ffd46b07639f","type":"change","z":"f888b812e6b0fc73","name":"","rules":[{"t":"set","p":"myFlowVar","pt":"flow","to":"","tot":"date"},{"t":"set","p":"#:(persistent)::myGlobalVar","pt":"global","to":"(\t $minimum := 1;\t $maximum := 10;\t $round(($random() * ($maximum-$minimum)) + $minimum, 0)\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1400,"y":100,"wires":[[]]},{"id":"21709d0c4e5a472c","type":"debug","z":"f888b812e6b0fc73","name":"debug 160","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1540,"y":160,"wires":[]}]
Just the function code
/**
* Set a value in context
* @param {'global'|'flow'|'context'} scope - The name of the scope
* @param {string} key - The key name to store against
* @param {any} val - The value to store in context
* @param {string} [store] - The name of the context store
*/
let asyncSetContext = (scope, key, val, store) => {
const theScope = globalThis[scope]
return new Promise((resolve, reject) => {
theScope.set(key, val, store, (error) => {
if (error) {
reject(error)
} else {
resolve()
}
})
})
}
/**
* Get a value from context
* @param {'global'|'flow'|'context'} scope - The name of the scope
* @param {string} key - The key name to get
* @param {string} [store] - The name of the context store
*/
let asyncGetContext = (scope, key, store) => {
const theScope = globalThis[scope]
return new Promise((resolve, reject) => {
theScope.get(key, store, (error, value) => {
if (error) {
reject(error)
} else {
resolve(value)
}
})
})
}
// get values
const myGlobalVar = await asyncGetContext('global', 'myGlobalVar', 'persistent')
const myFlowVar = await asyncGetContext('flow', 'myFlowVar', 'memory')
// set a value
await asyncSetContext('global', 'myNewGlobalVar', msg.payload, 'persistent')
msg.payload = {
myGlobalVar,
myFlowVar
}
return msg;
The better no-code (flow) way...
- copy global/flow variables to the msg using a change node
- pass the
msg
into a function/change/other node
- store the result in global once processed
Demo flow
[{"id":"7a12c01d8aa694fc","type":"inject","z":"f888b812e6b0fc73","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1220,"y":100,"wires":[["bd71ffd46b07639f"]]},{"id":"bd71ffd46b07639f","type":"change","z":"f888b812e6b0fc73","name":"","rules":[{"t":"set","p":"myFlowVar","pt":"flow","to":"","tot":"date"},{"t":"set","p":"#:(persistent)::myGlobalVar","pt":"global","to":"(\t $minimum := 1;\t $maximum := 10;\t $round(($random() * ($maximum-$minimum)) + $minimum, 0)\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1400,"y":100,"wires":[[]]},{"id":"50d1b30a387ab7ee","type":"change","z":"f888b812e6b0fc73","name":"copy flow/global to msg","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.myFlowVar","pt":"msg","to":"myFlowVar","tot":"flow"},{"t":"set","p":"payload.myGlobalVar","pt":"msg","to":"#:(persistent)::myGlobalVar","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":1410,"y":160,"wires":[["d9828892956c5f52"]]},{"id":"0e7da876a2959e73","type":"inject","z":"f888b812e6b0fc73","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1220,"y":160,"wires":[["50d1b30a387ab7ee"]]},{"id":"d9828892956c5f52","type":"function","z":"f888b812e6b0fc73","name":"use flow/global vars","func":"\nconst myGlobalVar = msg.payload.myGlobalVar\nconst myFlowVar = msg.payload.myFlowVar\nmsg.payload = {\n myGlobalVar,\n myFlowVar\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1390,"y":220,"wires":[["8f9ccce1a3d4963d"]]},{"id":"8f9ccce1a3d4963d","type":"change","z":"f888b812e6b0fc73","name":"myNewGlobalVar","rules":[{"t":"set","p":"myNewGlobalVar","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1390,"y":280,"wires":[["aeab6aea324bd1b4"]]}]
Just the function (could just as easily have been a no-code node like a change node!)...
const myGlobalVar = msg.payload.myGlobalVar
const myFlowVar = msg.payload.myFlowVar
msg.payload = {
myGlobalVar,
myFlowVar
}
return msg;
The common pitfall
Most users new to node-red (myself included) throw everything into function nodes. This doesnt make great "flow" programming. I mean you might as well just use node js
and skip node-red altogether.
Canned Text...
I recommend watching this playlist: Node-RED Essentials. The videos are done by the developers of node-red. They're nice & short and to the point. You will understand a whole lot more in about 1 hour. A small investment for a lot of gain.