# Stop infinity loop in function node using payload

**URL:** <https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999>\
**Category:** General\
**Created:** [12 January 2021 12:14 UTC](https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999 "2021-01-12T12:14:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![maxym](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/maxym/32/35240_2.png) [@maxym](https://discourse.nodered.org/u/maxym)\
**Post date:** [12 January 2021 12:14 UTC](https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999/1 "2021-01-12T12:14:56Z")

</div>

Hello all.  
This is my first post over here.

I had to write a simple simulation routine, which takes data from payload once, then spool the loop to generate a series of result values.  
After each iteration of that loop the node sends partial results using node.send() method.  
The loop is time-based: let's each iteration starts after a second.

How should I write such code to:

1. be able to set up time period between iterations?
2. be able to break the loop by sending 'stop' in input payload
3. be efficient: not block whole NR (I suppose active waiting could do that)

So far I did use the method shown in code below. Everything works but stopping the loop. Simply sending another payload to the input doesn't affect previously running loop at all.  
AFAK it runs the new instance of the whole code ( which is proven by sending two data payloads - it starts two separate simulations)

Is it possible to achieve that?

Thanks in advance

```auto
var c = 0;
var t;
var timer_is_on = 0;
var steps = 320; //48*2;
var inc = 4; // mins
var ts = new Date(msg.payload.ts);
ts.setUTCHours(0,0,0,0); 

if (msg.payload == 'stop') {
    stopCount(); 
    node.done(); 
}

function simulate() {
    msg.payload.ts = ts.getTime();
    ts.setUTCMinutes(ts.getUTCMinutes()+inc);
    node.send(msg); 
}  

function timedCount() {
   
  simulate(c); 
   
  c = c + 1;
  t = setTimeout(timedCount, 500);

  if (c>=steps) {
      stopCount();
  }
}

function startCount() {
  if (!timer_is_on) {
    timer_is_on = 1;
    timedCount();
  }
}

function stopCount() {
    node.error('stop');
  clearTimeout(t);
  timer_is_on = 0; 
}

startCount();

```

---

<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:** [12 January 2021 12:34 UTC](https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999/2 "2021-01-12T12:34:26Z")

</div>

Look at `setInterval()` and `setTimeout()`. [JavaScript Timing Events](https://www.w3schools.com/js/js_timing.asp)

---

<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:** [12 January 2021 12:37 UTC](https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999/3 "2021-01-12T12:37:11Z")

</div>

Welcome to the community.

Each time a msg is sent to a function node, the node is started from nothing. So as it stands, what you are doing won't work.

The easiest approach is to use the inject node to send a msg every x seconds. If you need do have a process that is \<1sec, you need to use a `setInterval` function in the function node. However, you have to save that interval function to a context variable and recover it each time the function node is called.

Here is a partial example from one of my own flows:

```javascript
let i = context.get('rainbow') || undefined

if ( i === undefined && msg.payload === 'start' ) {
    node.warn('starting')
    
   // ... do stuff here ...
    
    context.set('rainbow', i)
}

if ( i && msg.payload === 'stop' ) {
    node.warn('stopping')
    clearInterval(i)
    context.set('rainbow', undefined)
}

```

The context variable "rainbow" is used to store the interval function so that only 1 is used no matter how many msg's are sent to the function node. I send a msg.payload of "start" to start the timeout and "stop" to stop it.

---

<div class="post-metadata">

**Author:** ![maxym](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/maxym/32/35240_2.png) [@maxym](https://discourse.nodered.org/u/maxym)\
**Post date:** [12 January 2021 12:39 UTC](https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999/4 "2021-01-12T12:39:41Z")

</div>

As you can see in the code those functions are being used already.  
The point is, that I found to way to stop the loop being already executed by sending another payload to the same node. I need behaviour similar to delay node, where it is possible to control its behaviour initiated by previous message by sending another message.

---

<div class="post-metadata">

**Author:** ![maxym](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/maxym/32/35240_2.png) [@maxym](https://discourse.nodered.org/u/maxym)\
**Post date:** [12 January 2021 12:43 UTC](https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999/5 "2021-01-12T12:43:34Z")

</div>

Thank you.  
I forgot I can use context variables to pass information between calls. So easy idea.  
Thank you so much

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [13 March 2021 12:43 UTC](https://discourse.nodered.org/t/stop-infinity-loop-in-function-node-using-payload/38999/6 "2021-03-13T12:43:38Z")

</div>

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