# Message queue node that can be indexed

**URL:** <https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555>\
**Category:** General\
**Created:** [19 January 2020 01:23 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555 "2020-01-19T01:23:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [19 January 2020 01:23 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/1 "2020-01-19T01:23:01Z")

</div>

Problem:

- small screen. Can only display 1 message.
- Big size of messages to queue

I want the node to store/queue messages.  
If it gets a _next_ command, it shows the _next_ message.  
If it gets a _previous_ command, it shows the _previous_ message.  
_Wipe_ wipes the current message.  
_Wipe ALL_ wipes all messages.

Messages are output as requested.

This node _nearly_ does it.  
[Nearly!](https://flows.nodered.org/node/node-red-contrib-simple-message-queue)

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [19 January 2020 10:57 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/2 "2020-01-19T10:57:45Z")

</div>

Not difficult to do in a function node.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [19 January 2020 11:00 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/3 "2020-01-19T11:00:12Z")

</div>

(Blush) Yet beyond my skills at this time.

I get the idea of what to do, but just not the details like how to keep the queue and _step through_ it forward and backward.

Then there is the trick of deleting an entry.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [19 January 2020 11:51 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/4 "2020-01-19T11:51:56Z")

</div>

I guess the best place to start is to learn about arrays - [https://www.w3schools.com/js/js\_arrays.asp](https://www.w3schools.com/js/js_arrays.asp)  
and then the capabilities you have with them, index, push, pop, delete etc

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [19 January 2020 12:02 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/5 "2020-01-19T12:02:46Z")

</div>

Its 23:00 local here. Maybe tomorrow.

But thanks.

I may also look at the `simple-queue` node which I have and see if I can learn from it too.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [19 January 2020 12:28 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/6 "2020-01-19T12:28:16Z")

</div>

Well that is a queue (which probably uses an array ) - so will be discarding things once they are sent so you can't go back - but yes I guess it may be possible to modify. As the readme says it is based off a flow I wrote that is in the flows library so that may also be useful (as it just uses normal nodes and a function block to do the smarts)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [19 January 2020 12:29 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/7 "2020-01-19T12:29:53Z")

</div>

Well, I may look at it and get a _feel_ for how the array is made.

The stepping through may not be too good as it - as you say - wipes once read.  
I'm wanting to keep it.

Just saw an edit happen I think.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [19 January 2020 12:30 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/8 "2020-01-19T12:30:48Z")

</div>

Yes learn about arrays first.

---

<div class="post-metadata">

**Author:** ![cymplecy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/cymplecy/32/2773_2.png) [@cymplecy](https://discourse.nodered.org/u/cymplecy)\
**Post date:** [19 January 2020 15:50 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/9 "2020-01-19T15:50:45Z")

</div>

Nice little programming exercise 🙂

One thing I'd suggest is to use the concept of a control topic that @drmibell queue nodes use

e.g use a topic called control (it can be anything you like)

So any messages that don't have this as a topic get added to an array

Any messages with topic of control are the ones used to select which message in the array is output or wiped

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [19 January 2020 17:47 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/10 "2020-01-19T17:47:23Z")

</div>

Oops, should have posted this earlier, sorry.

* * *

In JavaScript, a queue can be as simple as a `list`. Better known as an `array`.

There are JS functions to add/remove to/from the beginning/end of an array, you can look them up easily on the Mozilla Developer Network (MDN) which is the best reference for JS statements and functions.

> **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)**
>
> The JavaScript Array class is a global object that is used in the construction of arrays; which are high-level, list-like objects.

So the data from a new msg would be added as a new entry to the end of an array (`myarray.push(....)`). You may wish to trim the array so that it doesn't grow infinitely and eventually run out of memory. You can do that by dropping the first entry of the array, there is a standard function for that (`myarray.shift()`).

You know the length of the array at any point because there is the `myarray.length` property. The first element is `myarray[0]`.

To get the last but one element of an array, you can do `myarray[myarray.length - 2]` or `myarray.slice(-2,-1)` - you should be able to work out how to access other parts of the array from that.

---

<div class="post-metadata">

**Author:** ![machadotiago](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/machadotiago/32/23776_2.png) [@machadotiago](https://discourse.nodered.org/u/machadotiago)\
**Post date:** [19 January 2020 18:48 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/11 "2020-01-19T18:48:49Z")

</div>

Well, maybe you could use a [FIFO](https://flows.nodered.org/flow/d7eea525606ea45a7c850976a85b349e) for that, but since you want to access the previous values, the correct way is to play with arrays (as @TotallyInformation brilliantly described above)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 January 2020 04:19 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/12 "2020-01-20T04:19:06Z")

</div>

I'm about to look at the other nodes I/we mentioned.

But this is what I have so far.

Strangely it doesn't work.  
When I try to _push_ data onto/into the array the index is never incremented.

```auto
var output = ""; // This is what returns the indexed value.
var i = 0;
let queue_array = [];
let index = context.get('SIZE') || 0;
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");

// This is where I hope the data is added to the array.
queue_array.push(msg.payload);
index = queue_array.length;

// This never gets above 1
node.warn("Index " + index);

context.set('pointer',index);
context.set('SIZE',index);
return;
//return msg;

```

On the _length_ part:  
From site:  
[Java script stuff - as earlier mentioned](https://www.w3schools.com/js/js_arrays.asp)  
var x = cars.length; // The length property returns the number of elements

```auto
index = queue_array.length;

```

Looks good enough to me.

(Yes, I have a bad habit of using _reserved_ words, but in the code none of them show up as being _commands_ so I hope that isn't a problem)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 January 2020 04:33 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/13 "2020-01-20T04:33:04Z")

</div>

I just tried the flow.

Ok.

Observation:

> Output 1 The first item on the top of the stack. It is sent only when `msg.topic == get` .

~~I am sending payloads with `topic == put` and I'm getting output 1 active.~~

Ok, that is behaving itself now.

> Output 2  
> The complete queue in Array format. It is sent every time a new item is added, removed or when `msg.topic == list`

Likewise. I am getting output form it when I sending `msg.topic == put`.

Not quite what I wrote, but here's the screen shot.

 ![Screenshot from 2020-01-20 15-37-43](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/7/97dd70a2db82e33079b1474fdcf6946d8d9db83b.png)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 January 2020 04:53 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/14 "2020-01-20T04:53:41Z")

</div>

Please don't take it as I'm upset.

I'm curious.

Looking inside your subflow:  
The _put_ node:

```auto
var queue = flow.get("queue")

if (!Array.isArray(queue)){
    queue = [];
}else if ( queue.length >= env.get("Buffer_Size") ){
    queue.pop(1);
}

queue.unshift(msg.payload);

flow.set("queue", queue);
msg.payload = queue;

return msg;

```

Ok,  
(physical line numbers)  
line 1: Beyond me. But I'm guessing it is getting the queue.  
line 4: Ok, if it isn't an array, make it an array.  
line 6: Check if the _length_ has changed. I'm not up to speed on `env.get` but kind of get it.  
line 7: POP! That is usually for taking things OFF a stack. As opposed to PUSH.  
But that's going back to my machine programming on the Z80. Anyway.  
line 10: queue.unshift? Yeah, ok.  
line 12: flow.set("queue",queue) Yeah. _queue_ defined in line 10 - kind of.

Nah. Way beyond my skill set.

I'll play with it but it is all _Greek_ to me.  
I looked at the other node and it is nearly the same code and at first looks it is just as confusing.

I may try to work out where it is different and see if I can associate that as to being the opposite of what this is doing.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [20 January 2020 08:00 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/15 "2020-01-20T08:00:42Z")

</div>

> [@Trying\_to\_learn](#):
>
> This never gets above 1

What do you see if you add a warn to show the length before the push?

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 January 2020 08:07 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/16 "2020-01-20T08:07:04Z")

</div>

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:

```auto
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:

```auto
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.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [20 January 2020 08:25 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/17 "2020-01-20T08:25:52Z")

</div>

> [@Trying\_to\_learn](#):
>
> Me suspects I am constantly re-making the array

Methinks thee is right.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 January 2020 08:32 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/18 "2020-01-20T08:32:09Z")

</div>

So when I add the code:

```auto
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......

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [20 January 2020 08:42 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/19 "2020-01-20T08:42:45Z")

</div>

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)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 January 2020 08:46 UTC](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555/20 "2020-01-20T08:46:36Z")

</div>

@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.)

[Next page](https://discourse.nodered.org/t/message-queue-node-that-can-be-indexed/20555.md?page=2)
