Stop Callback Loop - javascript

Below is a simplified version of my code.
I'm triggering the loop function repeatedly by using the callback loop();. That's great, but at some point in the future I want to be able to use my loopStart function to also stop the loop(); callback (and thus stop the repeated call of the function). How can I do that?
(function loopStart() {
triggerAudio('1.wav');
}());
function triggerAudio(soundFileName) {
(function loop() { // this function called repeatedly by callback
setTimeout(function() {
// some code
loop(); // callback
}, randomTime);
}());
}
I've seen examples using clearTimeout, but I suspect this won't work in this case since I'm not really stopping a setTimout?

I solved my question by changing setTimeout(function() { to myVar = setTimeout(function() { and using clearTimeout.
Here's the updated code:
(function loopStart() {
triggerAudio('1.wav');
setTimeout(function() {
clearTimeout(myVar); // using clearTimeout here
}, 5000);
}());
function triggerAudio(soundFileName) {
(function loop() { // this function called repeatedly by callback
myVar = setTimeout(function() { // added myVar = here
// some code
loop(); // callback
}, randomTime);
}());
}

Related

function call within setTimeout not executing

I am executing the function delayFilter() on keyup of an input box. I want to delay 1 second after the user stops typing and run the function filterProducts(). However, when executing filterProducts() inside of the setTimeout I get the console error "this.filterProducts is not a function". This function gets called fine when outside of the setTimeout. Why is this error being thrown?
delayFilter() {
let timeout = null;
clearTimeout(timeout);
timeout = setTimeout(function() {
this.filterProducts();
}, 1000);
}
filterProducts() {
//do stuff
}
That is because these, this inside the callback, does not refer to the object outside.
Try this:
delayFilter() {
let timeout = null;
clearTimeout(timeout);
let self = this;
timeout = setTimeout(function() {
self.filterProducts();
}, 1000);
}
filterProducts() {
//do stuff
}
You can also try the arrow function. The reason can be seen here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords.
delayFilter() {
let timeout = null;
clearTimeout(timeout);
timeout = setTimeout(() => {
this.filterProducts();
}, 1000);
}
filterProducts() {
//do stuff
}
You need to bind the scope of the function in the setTimeout callback. the easiest way is to use arrow functions, if your platform supports it.
timeout = setTimeout(() => this.filterProducts(), 1000);
you can also save the scope in a variable.
var self = this;
timeout = setTimeout(funciton() { self.filterProducts() }, 1000);
Alternatively you can manually bind it. This is useful if you want to pass the function around.
timeout = setTimeout(function() {...}.bind(this), 1000);

Calling two javascript functions one from each other

I have two functions for eg., runslider() and runslider1().
runslider() runs after the document is loaded and I need to call runslider1() after finishing runslider(). Then again runslider() after runslider1(). This process should happen like infinite loop. Can someone help me please.
I have tried to keep them like callbacks. But that didn't work.
function runSlider(runslider1){
alert("run")
runSlider1(runSlider());
}
function runSlider1(runslider){
alert("run1");
runSlider(runSlider1());
}
if you want your functions to be called over and over again try using setInterval
function runSlider(){
alert("run");
runSlider1();
}
function runSlider1(){
alert("run1");
}
setInterval(runSlider, 100);
This will cause both functions to be called in that order repeatedly every 100ms. It seems like this is the behavior you are looking for.
The comments above are correct - you will cause a stack overflow.
Don't know why you would need this, but I cleaned your code for you:
function runSlider() {
alert('run');
runSlider1();
}
function runSlider1() {
alert('run1');
runSlider();
}
You can create infinite loop like this you just need to call one function.
var runSlider = function() {
console.log("run")
runSlider1()
}
var runSlider1 = function() {
console.log("run1");
setTimeout(function() {
runSlider()
}, 1000)
}
runSlider()
Another solution is:
function runSlider() {
console.log("run");
runSlider1();
setTimeout(runSlider1(), 1000) // Calls runSlider1() after 1 second(1000 millisecond). You can change it.
}
function runSlider1() {
console.log("run1");
setTimeout(runSlider(), 1000) // Calls runSlider1() after 1 second(1000 millisecond).
}
runSlider(); // Starts the cycle
var maxCalls = 0;
function run1(cb) {
alert('run1');
if (maxCalls++ < 5) { //Added this to avoid an infinite loop
cb(run1); //We want the function run after cb to be this one
}
}
function run2(cb) {
alert('run2');
if (maxCalls++ < 5) {
cb(run2);
}
}
This is the way to call one function from another. If you create an infinite loop, you will freeze the browser up. If you want the two functions running constantly, its best to release execution for a bit with a setInterval call instead.
var runFunc = 0;
var run1 = function() {
alert('run1');
};
var run2 = function() {
alert('run2');
};
var run = function() {
!(++runFunc) ? run2 : run1; //Alternate between calling each function
}
var stopRunning = function() { //Call this to stop the functions running
clearInterval(runInterval);
};
var runInterval = setInterval(run, 1000); //Calls the function every second

Using clearInterval within a function to clear a setInterval on another function

I think im missing something fairly obvious with how the clearInterval method works.
So with the code below. I would expect the first function call to execute testFunction and set the interval to repeat the function. The 2nd call would execute the second function which will remove the interval from the 1st function. As this would execute far before the 5000ms interval the first function would not be executed again. However it does not behave like this.
Could someone please explain what is wrong with my method?
Reason for this is in a program I am writing I am making repeated get requests, every 30 seconds or so , using setTimeout but i would like a method to easily remove this interval at other points in the program
function testFunction() {
$("#test").append("test");
setTimeout(testFunction, 5000);
}
function stopFunction() {
clearTimeout(testFunction);
}
testFunction();
stopFunction();
setTimeout returns an ID so you should
var timeoutID = setTimeout(blah blah);
clearTimeout(timeoutID);
setTimeout returns an object that you need to pass into the clearTimeout method. See this article for an example: http://www.w3schools.com/jsref/met_win_cleartimeout.asp
setTimeout returns an identifier for the timer. Store this in a variable like:
var timeout;
function testFunction(){
...
timeout = setTimeout(testFunction, 5000);
}
function stopFunction(){
clearTimeout(timeout);
}
Here is a simple and I think better implementation for this .
var _timer = null,
_interval = 5000,
inProgress = false,
failures = 0,
MAX_FAILURES = 3;
function _update() {
// do request here, call _onResolve if no errors , and _onReject if errors
}
function _start() {
inProgress = true;
_update();
_timer = setInterval(_update, _interval);
}
function _end() {
inProgress = false;
clearInterval(_timer);
}
function _onReject(err) {
if (failures >= MAX_FAILURES) {
_end();
return false;
}
_end();
failures++;
_start();
}
function _onResolve(response) {
return true;
}

Can anyone explain why this JavaScript wont run

Im not very good wit JS and I just dont get why this wont work!
The code uses jquery to apply the pulsate efect to one of my divs and run forever unless I stop it with another function, but I cannot figure our why my first piece of code wont run!
function animate(var x){
// Do pulsate animation
$(x).effect("pulsate", { times:4 }, 5000);
// set timeout and recall after 10secs
setTimeout(animate, 10000);
}
$(document).ready(animate("#mydiv"));
Only way to get it working is for me to do this
function animate(){
// Do pulsate animation
$("#mydiv").effect("pulsate", { times:4 }, 5000);
// set timeout and recall after 10secs
setTimeout(animate, 10000);
}
$(document).ready(animate);
Note that in the first snippet the code uses variables to be more useful and the second piece has the selectors name hardcoded
Don't use var in your function declaration. Just use:
function animate(x){
Also, you probably want something like this for your first example:
function animate(x){
return function () {
function animateInner() {
$(x).effect("pulsate", { times:4 }, 5000);
setTimeout(animateInner, 10000);
}
animateInner();
};
}
$(document).ready(animate("#mydiv"));
DEMO: http://jsfiddle.net/XHKbC/
Otherwise, the original animate("#mydiv") call executes immediately (and $(x) probably won't find anything since the DOM isn't ready yet). $(document).ready() expects a reference to a function. You called a function instead. But that's all a little overkill. Just use:
$(document).ready(function () {
animate("#mydiv");
});
but you'll have to change your function so the setTimeout passes the value of x as well:
function animate(x){
// Do pulsate animation
$(x).effect("pulsate", { times:4 }, 5000);
// set timeout and recall after 10secs
setTimeout(function () {
animate(x);
}, 10000);
}
DEMO: http://jsfiddle.net/XHKbC/2/
Although it's a little more code/complex, my first example doesn't suffer the problem in my second (having to pass x in the setTimeout) by using a closure.
UPDATE:
Being shown how you are using this code, I'd set it up like this:
function Animater(target) {
var self = this;
var animateTO;
var animateElement = target;
function animate() {
animateElement.effect("pulsate", { times:4 }, 5000);
animateTO = setTimeout(animate, 10000);
}
self.start = function () {
animate();
};
self.stop = function () {
animateElement.finish();
clearTimeout(animateTO);
};
}
And create a new one like:
var mydivAnimater = new Animater($("#mydiv"));
You can then call .start() and .stop() on it, and you create any number of these Animater objects on different elements as you want.
DEMO: http://jsfiddle.net/K7bQC/3/
Your code has two issues:
omit the var:
function animate(x){
modify your event handler:
$(document).ready(function(){
animate("#mydiv");
});
You need to hand over a function reference (either animate or function(){}), not run the code right away which you are doing if you pass animate().
Now to not lose the reference to your x you have to modify the animate call in the timeout too:
setTimeout(function () {
animate(x);
}, 10000);
You dont need to type var when specifying a function parameter.

setTimeout and setInterval not working

I want to be able to call the function work() every 6 seconds. My jQuery code is
function looper(){
// do something
if (loopcheck) {
setInterval(work,6000);
}
else {
console.log('looper stopped');
}
}
The problem I am running into is that it loops over work twice quickly, and then it will wait for 6 seconds. i tried using setTimeout with similar results.
What could be causing work to be called twice before the delay works?
setInterval should be avoided. If you want work to be repeatedly called every 6 seconds, consider a recursive call to setTimeout instead
function loopWork(){
setTimeout(function () {
work();
loopWork();
}, 6000);
}
Then
function looper(){
// do something
if (loopcheck) {
loopWork()
}
else {
console.log('looper stopped');
}
}
And of course if you ever want to stop this, you'd save the value of the last call to setTimeout, and pass that to clearTimeout
var timeoutId;
timeoutId = setTimeout(function () {
work();
loopWork();
}, 6000);
Then to stop it
clearTimeout(timeoutId);
Use old-style setTimeout()
var i=0;
function work(){
console.log(i++);
}
function runner(){
work();
setTimeout(runner, 6000);
}
runner();
I prefer the following pattern myself I find it easier to follow:
function LoopingFunction() {
// do the work
setTimeout(arguments.callee, 6000); // call myself again in 6 seconds
}
And if you want to be able to stop it at any point:
var LoopingFunctionKeepGoing = true;
function LoopingFunction() {
if(!LoopingFunctionKeepGoing) return;
// do the work
setTimeout(arguments.callee, 6000); // call myself again in 6 seconds
}
Now you can stop it at any time by setting LoopingFunctionKeepGoing to false.

Categories

Resources