struggling with timeout function javascript [duplicate] - javascript

This question already has answers here:
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 9 years ago.
I'm trying to get this loop to work in javascript so it opens and closes an accordion at different intervals.... It only runs the loop once and stops. I'm banging my head against the wall as to why?
var i;
i = 0;
while (i < 999) {
setTimeout((function() {
return $("#money-slide").collapse("show");
}), 0);
setTimeout((function() {
return $("#money-slide").collapse("hide");
}), 4000);
setTimeout((function() {
return $("#collaboration-slide").collapse("show");
}), 4000);
setTimeout((function() {
return $("#collaboration-slide").collapse("hide");
}), 8000);
setTimeout((function() {
return $("#efficiency-slide").collapse("show");
}), 8000);
setTimeout((function() {
return $("#efficiency-slide").collapse("hide");
}), 12000);
setTimeout((function() {
return $("#communication-slide").collapse("show");
}), 12000);
setTimeout((function() {
return $("#communication-slide").collapse("hide");
}), 16000);
i++;
}

Use
setInterval
instead of
setTimeout
Also setTimeout ot setIterval are async , so returning anything from it won't do anything.
Try this
var i = 0;
var timer1, timer2, timew3, timer4, timer5, timer6, timer7, timer8;
setAnimationIntervals();
i = 0;
function setAnimationIntervals() {
timer1 = setInterval((function () {
$("#money-slide").collapse("show");
}), 0);
timer2 = setInterval((function () {
$("#money-slide").collapse("hide");
}), 4000);
timer3 = setInterval((function () {
$("#collaboration-slide").collapse("show");
}), 4000);
timer4 = setInterval((function () {
return $("#collaboration-slide").collapse("hide");
}), 8000);
timer5 = setInterval((function () {
$("#efficiency-slide").collapse("show");
}), 8000);
timer6 = setInterval((function () {
$("#efficiency-slide").collapse("hide");
}), 12000);
timer7 = setInterval((function () {
$("#communication-slide").collapse("show");
}), 12000);
timer8 = setInterval((function () {
$("#communication-slide").collapse("hide");
i++;
if (i === 999) {
clearAnimationIntervals();
}
}), 16000);
}
function clearAnimationIntervals {
clearInterval(timer1);
clearInterval(timer2);
clearInterval(timer3);
clearInterval(timer4);
clearInterval(timer5);
clearInterval(timer6);
clearInterval(timer7);
clearInterval(timer8);
}

Instead of setting your time-outs when the previous time-out has ended, you set all 999 time outs at once.
You need to set a new time-out in the time-out function. Or better use setInterval

the reason why it does it once is because you schedule so many timeouts in a loop, and then they all run simultaneously, and when each one is executed, it just stops. You would need to create another timeout from the timeout callback, or use setInterval.
Something along the lines of (not tested):
var money_slide_visible = false;
var money_slide_handler = function () {
$("#money-slide").collapse(money_slide_visible ? 'hide' : 'show');
money_slide_visible = !money_slide_visible;
setInterval(money_slide_handler, 4000);
};
money_slide_handler();

Related

How to kill and restart the recursive function in javascript

I am working on knockout js.
In that i have a recursive function which executes a function every minute. for that am using a timer every 60 sec it will execute also same will be reflecting in the UI also.
In my case, if i try to assign or initialize a timer value(observable) which is inside a loop, it doesn't reflecting instead of reflecting it is added to the pipeline and that much time loop is running simultaneously.
In that case i want to kill the loop and again want to restart every time i am changing the timer value.
timerInSec=60;
var loop = function () {
if (this.timer() < 1) {
myFunction()
this.timer(this.timerInSec - 1);
setTimeout(loop, 1000);
} else {
this.timer(this.timer() - 1);
setTimeout(loop, 1000);
}
};
loop();
Here is my solution. Please check.
timerInSec = 60;
const Loop = (function () {
let timer = 0;
let timerId = -1;
const myFunction = function () {
console.log('finished');
}
const fnLog = function (tm) {
console.log('current time = ', tm);
}
const fnProc = function () {
timerId = setTimeout(myFunction, 1000 * timer);
}
return {
start: function (tm = 60) {
this.stop();
timer = tm;
fnProc();
},
stop: function () {
if (timerId !== -1) {
clearTimeout(timerId);
timerId = -1;
}
}
}
})();
Loop.start(timerInSec);
setTimeout(() => {
Loop.start(timerInSec);
}, 500);

How to stop the jQuery's queue custom task which has setInterval() inside?

I have a custom animating effect task in jQuery queue. And there is a setInterval call inside it.
After some time the stop() function is being invoked. It removes the callback of currently executing task from the queue and starts executing the next one.
But setInterval from the previous effect (which already having been removed) is still running. Where should I place the clearInterval to be invoked after cancelling the task with calling the stop()?
Here is an example:
$('body')
.queue(function(next) {
var i = 0, el = this;
var interval = setInterval(function() {
el.style.backgroundColor = i++ % 2 == 0 ? '#500' : '#050';
if (i > 5) {
clearInterval(interval);
next();
}
}, 1000);
})
.queue(function() {
this.style.backgroundColor = '#005';
});
setTimeout(function() {
$('body').stop();
}, 1500);
https://jsfiddle.net/coderlex/tLd9xtjj/
Move your interval variable instantiation outside of the queue closure function, then you can clear it whenever you call stop().
var interval = null;
$('body')
.queue(function(next) {
var i = 0, el = this;
interval = setInterval(function() {
el.style.backgroundColor = i++ % 2 == 0 ? '#500' : '#050';
if (i > 5) {
clearInterval(interval);
interval = null;
next();
}
}, 1000);
})
.queue(function() {
this.style.backgroundColor = '#005';
});
setTimeout(function() {
$('body').stop();
if (interval != null) {
clearInterval(interval);
interval = null;
}
}, 1500);
Not sure about official support of this method, but after reading the jQuery sources it seems I've found the solution. There is an undocumented second argument given to the callback function of the queue task. That's the object of the current effect's hooks. The property we need named stop accordingly. If set, the closure is called only in case of manual effect stopping by stop() or finish() methods. It's not being called on clearing or setting new queue.
Here is an example:
$('body')
.queue(function(next, hooks) {
var i = 0, el = this;
var interval = setInterval(function() {
el.style.backgroundColor = i++ % 2 == 0 ? '#500' : '#050';
if (i > 5) {
clearInterval(interval);
next();
}
}, 1000);
hooks.stop = function() {
clearInterval(interval);
}
})
.queue(function(next) {
this.style.backgroundColor = '#005';
next();
});
setTimeout(function() {
$('body').stop();
}, 1500);

Check if there is active timeout in Javascript

Is there a way to find out if there are active timers ?
I have n-timers with different durations, for example:
Timer 1 -> 2-sec
Timer 2 -> 8-sec
..
...
Timer n -> n-sec
I need to know when all timers are finished
HTML
<div id="time-out-1">
Time out 1:<span></span>
</div>
<div id="time-out-2">
Time out 2:<span></span>
</div>
<button>
Are all timers finished ?
</button>
JS
setTimeout(function () {
$("#time-out-1 span").text("Finished !");
},2000);
setTimeout(function () {
$("#time-out-2 span").text("Finished !");
},8000);
$('button').click(function(){
// if all timers are finished
// do something
});
Jsfidle
Note: I need solution for this particular example because in my project there are n numbers of js files which might have timers that are declared like this example
Here's how I'd do it, create a wrapper around the native functions
(function(w) {
var active = {};
var _setTimeout = w.setTimeout;
var _clearTimeout = w.clearTimeout;
w.setTimeout = function(fn, delay) {
var id = _setTimeout(function() {
fn();
delete active[id];
}, delay);
active[id] = true;
return id;
}
w.clearTimeout = function(id) {
delete active[id];
_clearTimeout(id);
}
w.activeTimers = function() {
return Object.keys(active).length > 0;
}
})(window);
Then use it like
setTimeout(function () {
$("#time-out-1 span").text("Finished !");
},2000);
setTimeout(function () {
$("#time-out-2 span").text("Finished !");
},8000);
$('button').click(function(){
if ( window.activeTimers() ) {
// still something going on
} else {
// all done !
}
});
FIDDLE
May be this will help you.
//if n Timer then take count n
var count = 2;
setTimeout(function () {
count--;
$("#time-out-1 span").text("Finished !");
},2000);
setTimeout(function () {
count--;
$("#time-out-2 span").text("Finished !");
},8000);
$('button').click(function(){
//Check if all Timers are finished
if(count==0)
//finished
});
You can always add control variables.
var timer1_active = true,
timer2_active = true;
setTimeout(function () {
timer1_active = false;
$("#time-out-1 span").text("Finished !");
},2000);
setTimeout(function () {
timer2_active = false;
$("#time-out-2 span").text("Finished !");
},8000);
$('button').click(function(){
//Check if all Timers are finished
var finished = !timer1_active && !timer2_active;
});
I would do this with promises that jQuery offers. Consider this jsfiddle: https://jsfiddle.net/734y1oqy/
First we create an array for the promise objects:
var timers = [];
Then we create the promise objects themselves:
var timer1promise = $.Deferred();
var timer2promise = $.Deferred();
var timer3promise = $.Deferred();
Push them to array:
timers.push(timer1promise);
timers.push(timer2promise);
timers.push(timer3promise);
Create timers like normal, but have each timer resolve the corresponding promise object:
var timer1 = setTimeout(function() { console.log('timer 1 finished'); timer1promise.resolve(); }, 1000);
var timer2 = setTimeout(function() { console.log('timer 2 finished'); timer2promise.resolve(); }, 2000);
var timer3 = setTimeout(function() { console.log('timer 3 finished'); timer3promise.resolve(); }, 3000);
Create a thing that "watches" when every promise in the promise array is resolved:
$.when.apply($, timers).then(function()
{
console.log('All timers done!');
});
More info: https://api.jquery.com/category/deferred-object/

I want to repeat code but don't know how t use loops

I have this code:
js:
function change_color(color) {
$("body").animate({ backgroundColor:color }, '1000');
}
setTimeout(function () {
change_color('#4AC900'
);
}, 500);
setTimeout(function () {
change_color('#964514'
);
}, 1500);
setTimeout(function () {
change_color('#EE0000'
);
}, 1500);
setTimeout(function () {
change_color('#FFE303'
);
}, 1500);
setTimeout(function () {
change_color('#8E388E'
);
}, 1500);
setTimeout(function () {
change_color('#FF00AA'
);
}, 1500);
and I want to use it repeatedly but putting it in a while loop just crashes the site can anyone help?
Here is the site... its my little brothers site not mine... http://timothy.techbytbone.com/isaac.php
var colors = ['#4AC900', '#964514', '#EE0000', '#FFE303', '#8E388E', '#FF00AA'],
len = colors.length,
i;
for (i = 0; i < len; i++) {
(function(i, color) {
setTimeout(function () {
change_color(color);
}, (i + 1) * 500);
})(i, colors[i]);
}
this is all you need:
jsFiddle demo
var c = 0;
var colors = ['#4AC900','#964514','#EE0000','#FFE303','#8E388E','#FF00AA'];
(function loop(){
$('body').stop().animate({backgroundColor : colors[c++%colors.length] }, 1000, loop);
})();
(Prest attention that you need to use the jQuery UI to animate the CSS background-color property)
var colors = {'#4AC900': 500,
'#964514': 1500,
// etc. Just continue with the color-millisecond combinations
}
for(key in colors) {
setTimeout(function () {
change_color(key);
}, colors[key]);
}
Your loop is crashing because you can't set all the necessary timeouts at browser's loading. Here is a version of your code that should work.
var colors = ['#4AC900', '#964514', '#EE0000', '#FFE303', '#8E388E', '#FF00AA'];
var currentColorIndex = 0;
var scheduleChange;
scheduleChange = function() {
change_color(currentColorIndex);
currentColorIndex = (currentColorIndex + 1) % colors.length
setTimeout(scheduleChange, 1000);
};
setTimeout(scheduleChange, 500);
function change_color(color) {
$("body").animate({ backgroundColor:color }, '1000');
}
setTimeout(function() {
change_color('#4AC900')
}, 500);
colors = ['#964514', '#EE0000', '#FFE303', '#8E388E', '#FF00AA']
interval = setInterval(function() {
if (! a.length) {
return clearInterval(interval);
}
change_colors(a.shift());
}, 1500);
Have Fun. You should learn about closures for not messing setIntervals. There are tons of libraries that animate colors and other stuff. I can recommend morpheus by ded.

Why doesn't this simple JavaScript increment and decrement method work?

(function() {
var count = {
digit: 0,
increment: function() {
var interval = setInterval(function() {
if (++count.digit == 10) {
clearInterval(interval);
count.decrement();
}
var update = document.getElementById("liveUpdate");
update.innerHTML = count.digit;
}, 500);
},
decrement: function() {
var interval = setInterval(function() {
if (--count.digit == -1) {
clearInterval(interval);
}
}, 500);
}
};
count.increment();
})();
It stops but it doesn't go down? What could be the problem?
Your decrement function never updates the output anywhere. The variable is going down but you don't show that on screen.
Try (or check the corresponding JSFiddle):
(function() {
var update = document.getElementById("liveUpdate");
var count = {
digit: 0,
increment: function() {
var interval = setInterval(function() {
if (++count.digit == 10) {
clearInterval(interval);
count.decrement();
}
update.innerHTML = count.digit;
}, 500);
},
decrement: function() {
var interval = setInterval(function() {
if (--count.digit == -1) {
clearInterval(interval);
}
update.innerHTML = count.digit;
}, 500);
}
};
count.increment();
})();
setInterval will call the function every 500 seconds. It will not stop until you stop it. You can read more about stopping it at Stop setInterval call in JavaScript
It't not a bug, it's a feature ;-). setInterval() runs the given function in a loop with a given interval (500 ms). See this article for details.

Categories