user8869741
user8869741

Reputation:

How to stop looping function in Javascript

I'm controlling a Raspberry Pi with a bot and I'm simulating all the functions before implementation.

    function onFunction() {
        console.log("LED ON");
    }

    function offFunction() {
        console.log("LED OFF");
    }    
// blink:
    function loop(){
        onFunction();
        setTimeout(offFunction, 500);

        setTimeout(function(){ loop() }, 1000);
    }

I need this loop to stop when I call another function:

bot.hears(/off/i, (ctx) => {
    //break blink;
    offFunction();
});

I was trying to use a label and break but it doesn't seem to work with functions. Only with for, while loops.

Upvotes: 0

Views: 1052

Answers (3)

JBoulhous
JBoulhous

Reputation: 952

You can also define a timer, to use in your setTimeout on loop, and then clear it when needed.

var timer;   // <-- define timer
function onFunction() {
  console.log("LED ON");
}
function offFunction() {
  console.log("LED OFF");
}    
function loop(){
  onFunction();
  setTimeout(offFunction, 500);

  timer = setTimeout(function(){ loop() }, 1000); // <-- assign timer
}

bot.hears(/off/i, (ctx) => {
  //break blink;
  offFunction();
  clearTimeout(timer); // <-- clear timer
});

;-) hope this helps

Upvotes: 0

Alessandro Marchino
Alessandro Marchino

Reputation: 26

The setTimeout function (together with its counterpart setInterval) returns a timeoutId. This must be used with the function clearTimeout to cancel the timeout (similarly, clearInterval to cancel the interval). Therefore, the code should become

var loopTimeout;
var offTimeout;
function onFunction() {
    console.log("LED ON");
}

function offFunction() {
    console.log("LED OFF");
}    
// blink:
function loop(){
    onFunction();
    offTimeout = setTimeout(offFunction, 500);

    loopTimeout = setTimeout(function(){ loop() }, 1000);
}

bot.hears(/off/i, (ctx) => {
    //break blink;
    clearTimeout(offTimeout); // To try and prevent two 'offFunction' invocations
    clearTimeout(loopTimeout); // To clear the loop
    offFunction();
});

Upvotes: 1

Jonas Wilms
Jonas Wilms

Reputation: 138267

The unelegant solution would be a simple kill flag:

let kill = false;

function loop(){
    if(kill) return;
    onFunction();
    setTimeout(offFunction, 500);
    setTimeout( loop, 1000);
}

bot.hears(/off/i, (ctx) => {
  kill = true;
  offFunction();
});

Alternatively you could use an interval and stop that:

let isOn = false;
const blinking = setInterval(() => {
  console.log(`LED ${(isOn =! isOn) ? "ON": "OFF"}`);
}, 500);

bot.hears(/off/i, (ctx) => {
  clearInterval(blinking);
});

One might also use promises to do this:

const stop = new Promise((_, rej) => bot.hears(/off/i, rej));

const timer = ms => new Promise(res => setTimeout(res, ms);

(async function(){
   while(true){
     console.log("LED ON");
     await timer(500);
     console.log("LED OFF");
     await Promise.race([ timer(500), stop ]);
  }
})()

Upvotes: 0

Related Questions