Can't seem to generate an array in a flow variable

Hi all,

I have a function that works on multiple, asynchronous messages to build up a data structure. Since I don't want to wait on all messages to arrive, but wish to process updates on a message by message basis, it would seem I need to store the data in a flow variable since every time the function runs it destroys the original context variable.

Sadly, I am failing at this. I've stripped down my code to this bare essence example...

Here's the function code:

for (var i=0; i<=3; i++) {
    var sv= i;
    flow.set("test['sv']", sv);
   }
return;

Here's the flow (just an inject node and a function node):

[
    {
        "id": "5a236ef3db3f200a",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "2297f9823e4da39a",
        "type": "function",
        "z": "5a236ef3db3f200a",
        "name": "",
        "func": "for (var i=0; i<=3; i++) {\n    var sv= i;\n    flow.set(\"test['sv']\", sv);\n   }\nreturn;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 120,
        "wires": [
            []
        ]
    },
    {
        "id": "d1978d869fb36dfc",
        "type": "inject",
        "z": "5a236ef3db3f200a",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 390,
        "y": 120,
        "wires": [
            [
                "2297f9823e4da39a"
            ]
        ]
    }
]

And all I get is this when I expect it to show me "array [4]" and the four elements of the array.

Capture2

Thanks in advance for any help!

You treat sv as a string, instead as variable.
Try

flow.set("test[" + sv + "]", sv);

Hey there, here's a slightly different way to achieve what you want :

let test = [];

for (let i = 0; i <= 3 ; i++) {
    test.push(i);
}

flow.set("test", test);

return;

I concur with @Ithoh, it is just too complex and error prone to set individual array elements in context. It is better to create or modify the array and then save the whole array. There is no significant overhead in this as the context uses a reference to the whole array, so writing the array does not involve writing individual elements. For example you may end up with code that looks something like

let test = flow.get("test") || []
...
test[i] = someValue
...
flow.set("test", test)

@Ithoh and @Colin

Thanks so much for answering. I know a little about programming but next to nothing about Java or any modern language, which is why I chose Node Red to develop in. But of course you can't get away from it completely, so I'm a classic Java hack. Monkey see, monkey do!

I can't use your method, Ithoh, because I need to be able to index individual data on a consistent basis, i.e. I expect array index "n" to always hold certain data.

Your code, Colin, was exactly what the monkey needed to see and do. Now all is working perfectly :slightly_smiling_face:

Thank you!

Knowing about Java would not help at all, as this is javascript which is not related at all. Whoever thought of calling it that in the first place has a lot to answer for, it has caused no end of confusion over the years.

Well there you go, I don't even know what to call it properly! But you know what I mean :wink:

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