What do you see if you add a warn to show the length before the push?
It is 0
.
Me suspects I am constantly re-making the array, rather than checking if it exists - as per the code in the FIFO
subflow.
Thanks.
Stupid me didn't think of that.
Ok, not that easy.
If I replace the single push
with this:
queue_array.push("Message 1");
queue_array.push("Message 2");
queue_array.push("Message 3");
I see a starting index of 0
and an ending index of 3
. Which seems good.
But if I subsequently inject another message to invoke another 3 writes to the array.....
0 - 3.
So, I am either still wiping the array or something else.
This is how I modified to code:
var output = ""; // This is what returns the indexed value.
var i = 0; // This is for steping through the lists.
//let queue_array = [];
var queue_array = flow.get("queue") // I'm guessing this checks if the array exists.
if (!Array.isArray(queue_array))
{
queue_array = [];
}
// Yeah, I am not using the `else` option here. Becuase I don't understand it.
let index = context.get('SIZE') || 0; // I hope this part works. (See below)
index = queue_array.length; // This should get the *length* of the array.
node.warn("Index " + index);
if (msg.topic == "CONTROL")
{
// Stuff to be done with array.
if (msg.payload == "NEXT")
{
// Display next item
} else
if (msg.payload == "PREVIOUS")
{
// Display previous item
i = index - 1;
output = queue_array[i];
msg.payload = output
return msg;
} else
if (msg.payload == "WIPE")
{
// Delete this item
} else
if (msg.payload == "WIPE ALL")
{
// Wire the whole array
}
}
node.warn("saving data to array");
//queue_array.push(msg.payload);
queue_array.push("Message 1");
queue_array.push("Message 2");
queue_array.push("Message 3");
index = queue_array.length;
node.warn("Index " + index); // This shows me 3
context.set('pointer',index); // Save the value - for what ever reason.
context.set('SIZE',index); // This gets loaded next time (see above)
return;
//return msg;
I'll do a bit more digging/scratching.
Methinks thee is right.
So when I add the code:
var queue_array = flow.get("queue") // I'm guessing this checks if the array exists.
if (!Array.isArray(queue_array))
{
queue_array = [];
}
That would only happen if it didn't exist.
(As per the FIFO flow)
That is all I can resolve as the test to see if it is an array.
The queue.pop( )
isn't covered in the link supplied about JS arrays. The only pop
is for JS popup
which is a popup message.
So that has thrown me a curve ball.
And as I said: I take pop
as taking something off a stack/queue/what ever. and push
is to put things on.
Yeah, ok. I need to learn the difference. But pop
can't be a both way command - can it?
So unshift( )
is like a push
but rather than putting at the end of the array, it puts it at the start. Hmmmmm......
googling " javascript array pop " should be within you by now...
but yes I see you have found unshift... push and pop work on the end of the array and unshift and shift work on the front. (and delete works anywhere)
@dceejay, yeah, I've found the commands.
The order (queueing) I put them in the array is a bit academic to me at this stage.
The problem is the detecting the existence of the array.
if (!Array.isArray(queue))
Seems to be a sticking point.
I added code so if it sets up the array, it node.warn( )
me.
I inject and it sets up the array.
Pressing it a second time, it does the same.
So to me the problem is that - but am I right?
(Remember it is all Greek to me. I simply try to follow what I see.)
Well you first should try to get it from context... which I think you are doing.....
var queue_array = flow.get("queue") // I'm guessing this checks if the array exists.
but then at the end you have to save it back to context... otherwise next time it won't be there...
Woo - hoo!
I think that was lucky of me as I just worked that out - I think.
I added this to the end of the block:
flow.set('queue',queue_array);
But the output I am seeing is not understandable.
Oh, after looking a bit harder, I think I get it.
I'll apply it to the other node I am actually using and see if it helps.
Hmmmmm....
Ok, I think I have one part of it working.
But now I can't wipe the array when I want to. I have accidentally saved 15 entries and can't wipe them.
I thought the command would be queue_array = [];
because that was what I had before when it kept getting wiped.
This is a snip-it of the code:
if (msg.payload == "WIPE ALL")
{
// Wipe the whole array
node.warn("Initialising array");
queue_array = [];
return;
This is what is telling me the array isn't being wiped.
let index = context.get('SIZE') || 0; // I hope this part works. (See below)
node.warn("Index size from context " + index);
index = queue_array.length; // This should get the *length* of the array.
node.warn("Index size from array " + index);
I see 0
then for the second line I see 15
.
So I am still missing something.
Pop is covered in the link that I gave. Just after map
and before push
.
You didn't write it back again so you didn't save the change.
D'oh! Yeah. Silly me.
I really must make idiots look smart.
You have some other logic issues too. As your code stands, you will never have a next
will you? That's because you are adding to the queue after your other logic, I think that you need to add to it first?
True.
The idea is that things are put in the array.
As they are put in, the only one I can really use is the previous one.
But
I scroll back a few entries and what ever. I may want to go to the next entry too.
I'm working on it. Found quite a few problems with how the pointers are kept, etc.
Be Back Soon.
Ok, I'm stuck.
node.warn("Next entry " + i+1);
Doesn't work.
I get 11
if i = 1
.
Is there a way - without introducing a new variable to get it to show i+1?
This flow works - as best I can tell.
The node counters are NOT zero counting which I think helps with seeing which message you are viewing.
Could you help me with a more tidy way with the variable j
in the scheme of things.
That doesn't mean directly you. But more a general request for help.
Sorry the main function
node still has a bit of old stuff in it.
That's the node with the j
variable in it.
The node shows how many entries in the array. NOT zero counting.
So as the node shows the index number, I wanted it to also be non-zero counting.
Found a couple of spelling mistakes.
[{"id":"8e458e68.2f8d88","type":"function","z":"184dc884.7aba5f","name":"Array","func":"//\nvar output = \"\"; // This is what returns the indexed value.\nvar i = context.get('pointer') || 0;\nvar j = 0;\nvar queue_array = flow.get(\"queue\") // I'm guessing this checks if the array exists.\nif (!Array.isArray(queue_array))\n{\n // If not, set up array.\n node.warn(\"Initialising array\");\n queue_array = [];\n flow.set('queue',queue_array);\n node.warn(\"Array set up.\");\n}\n\nsize = queue_array.length;\n\nif (msg.topic == \"CONTROL\")\n{\n // Stuff to be done with array.\n if (msg.payload == \"NEXT\")\n {\n // Display next item\n i = i + 1;\n j = i + 1;\n node.warn(\"Next entry \" + j);\n output = queue_array[i];\n msg.payload = output;\n context.set('pointer',i); // Save the value.\n node.status(size + \" \" + j);\n return msg;\n } else\n if (msg.payload == \"PREVIOUS\")\n {\n // Display previous item\n i = i - 1;\n j = i + 1;\n node.warn(\"Previous entry \" + j);\n output = queue_array[i];\n msg.payload = output;\n context.set('pointer',i); // Save the value.\n node.status(size + \" \" + j);\n return msg;\n } else\n if (msg.payload == \"WIPE\")\n {\n // Delete this item\n } else\n if (msg.payload == \"WIPE ALL\")\n {\n // Wipe the whole array\n node.warn(\"Initialising array\");\n queue_array = [];\n flow.set('queue',queue_array);\n node.warn(\"Array Wiped.\");\n return;\n }\n}\n\nnode.warn(\"saving data to array\");\n\nqueue_array.push(msg.payload);\n\nsize = queue_array.length;\n\ncontext.set('pointer',i); // Save the value - for what ever reason.\n\nflow.set('queue',queue_array);\nnode.status(size + \" \" + pointer);\n\nreturn;\n","outputs":1,"noerr":0,"x":490,"y":1320,"wires":[["e09fc19c.cf203"]]},{"id":"c0ef557b.139f1","type":"template","z":"184dc884.7aba5f","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Message {{payload}}","output":"str","x":230,"y":1280,"wires":[["8e458e68.2f8d88","fcb9dca0.971b5"]]},{"id":"e09fc19c.cf203","type":"debug","z":"184dc884.7aba5f","name":"Index result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":650,"y":1320,"wires":[]},{"id":"c4bbdffc.81ab78","type":"inject","z":"184dc884.7aba5f","name":"Next","topic":"CONTROL","payload":"NEXT","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":240,"y":1360,"wires":[["8e458e68.2f8d88"]]},{"id":"16235d1e.a6c2db","type":"inject","z":"184dc884.7aba5f","name":"Previous","topic":"CONTROL","payload":"PREVIOUS","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":1390,"wires":[["8e458e68.2f8d88"]]},{"id":"8d565471.b8f5a","type":"inject","z":"184dc884.7aba5f","name":"Wipe All","topic":"CONTROL","payload":"WIPE ALL","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":1470,"wires":[["8e458e68.2f8d88"]]},{"id":"bb6554dd.38b188","type":"inject","z":"184dc884.7aba5f","name":"Wipe","topic":"CONTROL","payload":"WIPE","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":240,"y":1440,"wires":[["8e458e68.2f8d88"]]},{"id":"26162964.640a16","type":"random","z":"184dc884.7aba5f","name":"Random number","low":"1","high":"10","inte":"true","property":"payload","x":200,"y":1250,"wires":[["c0ef557b.139f1"]]},{"id":"fcb9dca0.971b5","type":"debug","z":"184dc884.7aba5f","name":"History","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":500,"y":1230,"wires":[]},{"id":"638c9635.68a788","type":"inject","z":"184dc884.7aba5f","name":"Add new item to array","topic":"","payload":"blah_","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1220,"wires":[["26162964.640a16"]]}]
And this is for the single wipe
part of the function
node code:
// Delete this item
j = i + 1;
node.warn("Removing item " + j + " which is " + queue_array[i]);
queue_array.splice(i,1);
flow.set('queue', queue_array);
return;
All seems to work as I want.
(Just copy/paste this in the code at the delete this item
part is. Which as posted is basically empty.)
Could someone give it a sanity check?
Please.
The problem here is JavaScript uses the +
symbol for both joining strings and adding numbers.
Because your statement has a string in it (the "Next entry "
part), it will assume it should treat everything as a string, so the 1
ends up being 11
- just as 8
would end up as 81
.
The trick is to give the JavaScript interpreter a hint as to what order it should do the operations. I see you've used spaces in your statement, but you need to use brackets:
node.warn("Next entry " + (i+1) );
With those brackets, it will first do the i+1
- where both sides are numbers, so it does numeric addition. It then does "Next entry " + <result of (i+1)>
where there is a String, so it does a string join.
I hope that clarifies it.
Yes, thanks Nic.
I was suspicious of doing that. It is I have just spent the last . . . . (long time) getting this working and am starting to lose self belief.
I'll go in and modify the code now.
That kind of lies with the old BASIC syntax. But . . . . . I am good at messing things up and just hadn't got around to trying that.
Self doubt isn't a good thing.
I've posted the working flow here if you want to look at it and have a look at what I did.
Since we should all now be using newer versions of Node.js, we can also make use of ES6 features. So a nice way to output a string with an embedded simple calculation is:
node.warn( `Next entry ${i+1}` );
Note the backticks
I think us JS muggles should stick with the simplest way of doing something
You wizards can do things the fancy ways
#KISS
Haha, I would argue that, in this case, the fancy way may well be the easiest
Anyway, it is through learning new ways that we keep ourselves youthful - or "childish" as our better halves would doubtless characterise things.