Delay inside function node between messages?

#1

Hi! I am a newbie of NodeRed and loving it so far. Thank you all for this amazing tool!
In this example from documentation is it posible to have a delays between messages inside the function node?

var msg1 = { payload:"first out of output 1" };
var msg2 = { payload:"second out of output 1" };
var msg3 = { payload:"third out of output 1" };
var msg4 = { payload:"only message from output 2" };
return [ [ msg1, msg2, msg3 ], msg4 ];

thx! :slight_smile:

0 Likes

#2

Yes, but it involves some slightly more advanced javascript, using setTimeout. To avoid this you could send them all to separate outputs then use delay nodes on the outputs and merge them back together again.

1 Like

#3

Another non-blocking option would be to use a 'triggered flow'.

An example of a triggered flow can be found https://gist.github.com/Paul-Reed/c29cfa755fed666805956eb6da42a0d0 which I use to ensure that the flow carries out instructions in a set order - and when the previous instruction has completed.

Paul

EDIT// A better example of a triggered flow -https://gist.github.com/dceejay/cea8afa28b7a93ebdc0f

0 Likes

#4

Yet another option, haven't tried it myself, but take a look at https://flows.nodered.org/node/node-red-contrib-simple-message-queue

0 Likes

#5

This should do what you want, using just the delay node.

[{"id":"55680c13.4953a4","type":"debug","z":"7920414b.cfa4f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":650,"y":120,"wires":[]},{"id":"85c8db46.a1272","type":"function","z":"7920414b.cfa4f8","name":"","func":"// msg.delay is in milliseconds\nvar msg1 = { payload:\"first out of output 1\", delay:10000 };\n// if msg.delay is undefined, the delay node uses default\nvar msg2 = { payload:\"second out of output 1\" };\nvar msg3 = { payload:\"third out of output 1\", delay:0};\nvar msg4 = { payload:\"only message from output 2\"};\nreturn [ [ msg1, msg2, msg3 ], msg4 ];","outputs":2,"noerr":0,"x":370,"y":160,"wires":[["c600d120.54da78"],["88475b70.b765b"]]},{"id":"3b9f76b1.35359a","type":"inject","z":"7920414b.cfa4f8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":240,"y":160,"wires":[["85c8db46.a1272"]]},{"id":"c600d120.54da78","type":"delay","z":"7920414b.cfa4f8","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":520,"y":120,"wires":[["55680c13.4953a4"]]},{"id":"88475b70.b765b","type":"debug","z":"7920414b.cfa4f8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":510,"y":200,"wires":[]}]
0 Likes

#6

The resulting order is incorrect;

sweet

0 Likes

#7

@Paul-Reed No, the delays were set deliberately in the function node to show what could be done: msg1 delayed by 10 s, msg2 with default (5 s), and msg3 with no delay. Clearly, if you want to preserve the order you have to set progressively increasing delays. Sorry for the confusion.

0 Likes

#8

Hi, This is what I was trying but only find some examples in node.status... inside function before return msg.
So is it posible to have timeout inside the return? You have a simple example or some link to learn how? I tried but I can t figure out...
Thank you again.

0 Likes

#9

Thank you Paul. I will try. I just need to figure out so many things first. In this case would be much better for me just to set timeouts on the return msg if is posible.
Any link o reference will be very helpful... Thank you again.

0 Likes

#10

If you choose to use a 'triggered flow', the easiest option is to use node-red-contrib-simple-message-queue and there is information in the node readme about the various options available.
This node is basically @dceejay's 'triggered flow' example wrapped up into a node, and works on the same principle.

If you want a simple flow to demonstrate it working, install the node-red-contrib-simple-message-queue node (it's in the node-RED library), and then import the flow below.

Click the inject node and 5 messages will be injected into the flow, the first message will travel straight through the 'queue' node, and the remaining four will be queued, and released in sequence, as the preceding message acknowledges that it's been completed.
The delay node slows down the flow, so you can see what's happening, and simulates time taken to complete each action.

[
    {
        "id": "ca4b5b70.5a0678",
        "type": "simple-queue",
        "z": "c53060.842a0fa",
        "name": "queue",
        "firstMessageBypass": true,
        "bypassInterval": "30000",
        "x": 620,
        "y": 790,
        "wires": [
            [
                "ec60a83b.a96518"
            ]
        ]
    },
    {
        "id": "ae67f50a.990b88",
        "type": "change",
        "z": "c53060.842a0fa",
        "name": "release next msg",
        "rules": [
            {
                "t": "set",
                "p": "trigger",
                "pt": "msg",
                "to": "1",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 620,
        "y": 720,
        "wires": [
            [
                "ca4b5b70.5a0678"
            ]
        ]
    },
    {
        "id": "ec60a83b.a96518",
        "type": "delay",
        "z": "c53060.842a0fa",
        "name": "simulate delay in running function",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "x": 850,
        "y": 790,
        "wires": [
            [
                "ae67f50a.990b88",
                "3ecbc006.f8586"
            ]
        ]
    },
    {
        "id": "8e3df100.38b86",
        "type": "inject",
        "z": "c53060.842a0fa",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 240,
        "y": 790,
        "wires": [
            [
                "b49e71eb.d2c9b"
            ]
        ]
    },
    {
        "id": "3ecbc006.f8586",
        "type": "debug",
        "z": "c53060.842a0fa",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "x": 940,
        "y": 840,
        "wires": []
    },
    {
        "id": "b49e71eb.d2c9b",
        "type": "function",
        "z": "c53060.842a0fa",
        "name": "Create some msg's",
        "func": "var msg1 = { payload:\"first out of output\" };\nvar msg2 = { payload:\"second out of output\" };\nvar msg3 = { payload:\"third out of output\" };\nvar msg4 = { payload:\"fourth out of output\" };\nvar msg5 = { payload:\"fifth out of output\" };\nreturn [[ msg1, msg2, msg3, msg4, msg5 ]];",
        "outputs": 2,
        "noerr": 0,
        "x": 430,
        "y": 790,
        "wires": [
            [
                "ca4b5b70.5a0678"
            ],
            []
        ]
    }
]
0 Likes

#11

Hi!
I tried and I see that is working but I really don t understand why... This release next message cross flow ... it s too much. With this setup is it necessary the delay?
I would love also to have control of the time between the messages... not to a fixed interval... let s say 5 seconds and after another message after 15 seconds... just a simple java timeout...
Thanks for your help anyway... I will use this triggered flow in another setup for the garden.
Thank you again

0 Likes

#12

Just reconfigure the node to set the bypass interval, like this;

[
    {
        "id": "ca4b5b70.5a0678",
        "type": "simple-queue",
        "z": "c53060.842a0fa",
        "name": "queue",
        "firstMessageBypass": true,
        "bypassInterval": "15000",
        "x": 620,
        "y": 790,
        "wires": [
            [
                "3ecbc006.f8586"
            ]
        ]
    },
    {
        "id": "8e3df100.38b86",
        "type": "inject",
        "z": "c53060.842a0fa",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 240,
        "y": 790,
        "wires": [
            [
                "b49e71eb.d2c9b"
            ]
        ]
    },
    {
        "id": "3ecbc006.f8586",
        "type": "debug",
        "z": "c53060.842a0fa",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "x": 800,
        "y": 790,
        "wires": []
    },
    {
        "id": "b49e71eb.d2c9b",
        "type": "function",
        "z": "c53060.842a0fa",
        "name": "Create some msg's",
        "func": "var msg1 = { payload:\"first out of output\" };\nvar msg2 = { payload:\"second out of output\" };\nvar msg3 = { payload:\"third out of output\" };\nvar msg4 = { payload:\"fourth out of output\" };\nvar msg5 = { payload:\"fifth out of output\" };\nreturn [[ msg1, msg2, msg3, msg4, msg5 ]];",
        "outputs": 2,
        "noerr": 0,
        "x": 430,
        "y": 790,
        "wires": [
            [
                "ca4b5b70.5a0678"
            ],
            []
        ]
    }
]
0 Likes

#13

I understand but I need every message to have different times betwwen them... not always 15.
Thanks anyway...

0 Likes

#14

If you want to do it yourself in a function node then as I said you will have to use setTimeout() in the code. Search for setTimeout in this forum and you will find some examples. However, if you are a beginner at js, you may well have some problems with the concepts. Sometimes it is better to learn to walk before trying to run.

1 Like

#15

You can also do some split/join trickery and preserve your msg.parts.index property in each flow, dump the joined flows into elements in an array, and use the change node to use the array's elements to build your final desired result.

edit: you also need to preserve most of the other msg.parts properties, especially the msg.parts.id, though if there are any parts you intend to omit, you can do so and then change the msg.parts.count property on all of the various flows; doing so will make it so the join node will sit there and wait until it has the right number of parts with a matching msg.parts.id before sending the combined object/array onward. (I haven't tried this with significant delays between the parts, but this makes me want to test if it's non-blocking...)

0 Likes