# Can I have a delay / sleep inside Function node

**URL:** <https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101>\
**Category:** General\
**Created:** [13 September 2018 07:50 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101 "2018-09-13T07:50:19Z")\
**Posts on this page:** 15\
**Page:** 2

<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:** [18 July 2019 06:59 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/25 "2019-07-18T06:59:51Z")

</div>

Is it a value you set once ? Or is it dynamic ?

---

<div class="post-metadata">

**Author:** ![jovee](https://avatars.discourse-cdn.com/v4/letter/j/bbce88/32.png) [@jovee](https://discourse.nodered.org/u/jovee)\
**Post date:** [18 July 2019 17:00 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/26 "2019-07-18T17:00:11Z")

</div>

Ideally dynamic, as the system could adjust its own timing to compensate for additional tasks it receives from outside sources. That’s why I’d like to use a function.

---

<div class="post-metadata">

**Author:** ![jovee](https://avatars.discourse-cdn.com/v4/letter/j/bbce88/32.png) [@jovee](https://discourse.nodered.org/u/jovee)\
**Post date:** [18 July 2019 22:44 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/27 "2019-07-18T22:44:06Z")

</div>

Here's a description of the current project, for some context, if you're interested 🙂

> [@Set trigger node's delay time from context value](https://discourse.nodered.org/t/set-trigger-nodes-delay-time-from-context-value/13415/9):
>
> Sure, don't mind explaining at all! And great suggestion, but I'm using msg.topic later on in the flow to help track what device a TCP response came from. I'm sure there's another way to do it, but that's what I've got right now. This part of the flow is meant to collect a bunch of information from a group of display hardware, projectors in this case, and save the states collected to context storage, to be accessed at anytime by other systems that need the information. Data collected are things…

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [28 December 2023 12:24 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/28 "2023-12-28T12:24:28Z")

</div>

Let's me go back to the original question. I have a logic where I need to implement some delay. I have to do it in a way that I stay inside a loop of my existing logic.

I did this proof of concept code which should delay the output by `msg.payload` seconds.

The idea was that I create a while loop which loops until a counter reaches the designed `msg.payload` value. And within this loop I create a `setTimeout` function that increases this internal timer advancing it by 1 second each time:

```auto
let sleepcounter = 0;
let lastcounter = -1;

while (sleepcounter < msg.payload) {
    node.warn("While "+sleepcounter+"<"+msg.payload);
    if (lastcounter !== sleepcounter) {
        lastcounter = sleepcounter;
        setTimeout(function () {
            sleepcounter++;
        }, 1000);
        node.send({"payload": sleepcounter});
        node.status({ fill: "blue", shape: "ring", text: sleepcounter });
    }
}
return msg;

```

I must have done something terrible. I added a `node.warn` also a `node.send` and `node.status` so I can see what the code is doing, but it is doing nothing. And I think also crashing node-red.  
The `if` statement was added so the code does not call `setTimeout` all the time, only until the timer actual expired and it is ready to be called again.

How come I am not seeing anything on the node status or the debugger?

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [28 December 2023 12:35 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/29 "2023-12-28T12:35:11Z")

</div>

> [@nygma2004](#):
>
> I have to do it in a way that I stay inside a loop of my existing logic

Why?

> [@nygma2004](#):
>
> How come I am not seeing anything on the node status or the debugger?

Because the loop happens so fast and exits. IE it is not doing what you think it is.

* * *

Truth bomb: avoid loops in functions where possible (unless you are using fixed small sized loops where they will definitely exit and not crash the node runtime). The nodejs runtime is a single threaded event loop & running loops will block the event loop causing poor performance and other side effects.

* * *

If you explain what you are doing and what you are trying to achieve we can advise.

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [28 December 2023 13:05 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/30 "2023-12-28T13:05:16Z")

</div>

I am building a general purpose rule engine where I define various conditions (like if a sensor value is above a certain threshold) and if the conditions are met, there are a set of instructions to perform. Maybe turn on a lamp, wait, turn it off and also do something else.  
I expect the code to do something after the delay (not just sending data) this is why I wanted to keep the processing within the loop.

I know my other option would be to send the data out on a second output and loop in back to the input through a delay node. And in that case I would also need to pass the entire context so the code can pick up the processing after the delay. Not impossible to do, but I was hoping to keep it simple and be able to delay the processing inside the function node.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [28 December 2023 13:17 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/31 "2023-12-28T13:17:18Z")

</div>

For this kind of thing, a delay is not ideal IMO. An alternative to consider would be generating schedules (something like cron-plus) can have dynamically generated schedules that trigger when needed (you can also programmatically set the payload it emits)

As for your rule engine, if suggest making it from standard nodes in particular the link call in dynamic mode - which can be used to dynamically branch to areas of code based on some property value.

The most important part to remember node (and thus node-red) is primarily event based. Your solution should (ideally) be built with that in mind.

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [28 December 2023 13:46 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/32 "2023-12-28T13:46:29Z")

</div>

Thanks for these insight. I have done scheduling before, I think I can re-use that logic. Probably save the entire context for the schedule and change my code that it can return the execution after the delay step.  
Should be doable.

---

<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:** [28 December 2023 15:13 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/33 "2023-12-28T15:13:43Z")

</div>

There is nothing wrong with using a single setTimeout within a function as you can ensure you pass the correct context to the internal function. But looping is tricky (as you found) so generally best to avoid.

---

<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:** [28 December 2023 15:42 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/34 "2023-12-28T15:42:42Z")

</div>

For completeness, the reason your code did not work, that the code

```auto
        lastcounter = sleepcounter;
        setTimeout(function () {
            sleepcounter++;
        }, 1000);
        node.send({"payload": sleepcounter});
        node.status({ fill: "blue", shape: "ring", text: sleepcounter });

```

starts the timer, but then immediately sends the message and the status. You would need to put the send and status calls inside the function to make them happen after 1 second. But you would also have to restructure the whole thing to get it to do what you want. Basically this technique is to be avoided if possible. It is tricky to get it right.

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [28 December 2023 16:22 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/35 "2023-12-28T16:22:38Z")

</div>

> [@Colin](#):
>
> You would need to put the send and status calls inside the function to make them happen after 1 second.

I wanted it to go out immediately, and the if statement was supposed to stop `setTimeout` to be started again if it is already running.  
`if (lastcounter !== sleepcounter)` should only be true initially or after the timer function incremeneted a sleepcounter. In that case a timer will be triggered again...

---

<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:** [28 December 2023 16:52 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/36 "2023-12-28T16:52:25Z")

</div>

> [@nygma2004](#):
>
> I wanted it to go out immediately

Ok, I see what you are trying to do. The problem is that your code will sit, hogging the processor and stopping anything else going on, running round your loop at top speed waiting for the timer to run down. The result is that everything else going on in node red stops, so the dashboard will stop, no messages will get handled.

---

<div class="post-metadata">

**Author:** ![Frida](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/frida/32/68250_2.png) [@Frida](https://discourse.nodered.org/u/Frida)\
**Post date:** [29 December 2023 08:34 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/37 "2023-12-29T08:34:07Z")

</div>

Maybe it's something you can use?

```auto
[{"id":"f16f1303aec8dfdb","type":"function","z":"da612d68cde527a4","name":"Timeout","func":"let msg1 = {}\nlet timeout = msg.payload // sec\n\nlet MyTimeOutID = context.get('MyTimeOutID') ?? undefined\n\nmsg1 = { payload: 'Done' }\n\nfunction MyTimeOut() {\n if (MyTimeOutID != undefined) { clearTimeout(MyTimeOutID) }\n MyTimeOutID = setTimeout(function () {\n clearTimeout(MyTimeOutID)\n node.send(msg1)\n }, 1000 * timeout)\n}\n\nMyTimeOut()","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":1120,"wires":[["ef447c2c8430f28b"]]},{"id":"a10d62e7f60f8f58","type":"inject","z":"da612d68cde527a4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":190,"y":1060,"wires":[["f16f1303aec8dfdb"]]},{"id":"b46aaa672e12435c","type":"inject","z":"da612d68cde527a4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":190,"y":1100,"wires":[["f16f1303aec8dfdb"]]},{"id":"aabc209e36dcb703","type":"inject","z":"da612d68cde527a4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"3","payloadType":"num","x":190,"y":1140,"wires":[["f16f1303aec8dfdb"]]},{"id":"d5109337a1d74ca7","type":"inject","z":"da612d68cde527a4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"5","payloadType":"num","x":190,"y":1180,"wires":[["f16f1303aec8dfdb"]]},{"id":"ef447c2c8430f28b","type":"debug","z":"da612d68cde527a4","name":"debug 349","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":1120,"wires":[]}]

```

 ![pic01](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/1/c1dd76564357b953984925845d5165b751226da0.png)

---

<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:** [29 December 2023 10:50 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/38 "2023-12-29T10:50:00Z")

</div>

That can be done with a Delay node

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/9/b9caded702176127a259959a78de40bedf2e017c.png)

```auto
[{"id":"bea323d7f318928b","type":"inject","z":"bdd7be38.d3b55","name":"0","props":[{"p":"payload"},{"p":"delay","v":"0","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Done","payloadType":"str","x":150,"y":4220,"wires":[["0fc48874801a9618"]]},{"id":"7e19a24d12238d4a","type":"inject","z":"bdd7be38.d3b55","name":"1","props":[{"p":"payload"},{"p":"delay","v":"1000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Done","payloadType":"str","x":150,"y":4260,"wires":[["0fc48874801a9618"]]},{"id":"206b347015db8685","type":"inject","z":"bdd7be38.d3b55","name":"3","props":[{"p":"payload"},{"p":"delay","v":"3000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Done","payloadType":"str","x":150,"y":4300,"wires":[["0fc48874801a9618"]]},{"id":"de6dab64a58a2255","type":"inject","z":"bdd7be38.d3b55","name":"5","props":[{"p":"payload"},{"p":"delay","v":"5000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Done","payloadType":"str","x":150,"y":4340,"wires":[["0fc48874801a9618"]]},{"id":"0fc48874801a9618","type":"delay","z":"bdd7be38.d3b55","name":"Delay","pauseType":"delayv","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":370,"y":4280,"wires":[["cbe452e6f1189943"]]},{"id":"cbe452e6f1189943","type":"debug","z":"bdd7be38.d3b55","name":"debug 2478","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":4280,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [7 February 2024 06:39 UTC](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101/39 "2024-02-07T06:39:33Z")

</div>

Thanks, I will check if that keeps the process running as mentioned above.

[Previous page](https://discourse.nodered.org/t/can-i-have-a-delay-sleep-inside-function-node/3101.md?page=1)
