Here is my code
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
alert(i);
}, 2000);
setTimeout(function() {
i--;
DeleteREG(i);
}, 800);
}
}, 4000);
})(5);
})();
According to the code it should alert at i=5,4,3,2,1.But it alerts at i=4,3,2,1,0.Can anyone please explain me why it is not working?what should be rectified to the code to work properly?Same thing happens for the following code also
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
alert(i);
}, 2000);
i--;
DeleteREG(i);
}
}, 4000);
})(5);
})();
And please explain me the solution in written format.How to get rid of this problem?
When you call setTimeout, your code doesn't stop.
Those two functions defined here :
setTimeout(function stop_() {
alert(i);
}, 2000);
setTimeout(function() {
i--;
DeleteREG(i);
}, 800);
They're called 2000 and 800 ms after the same moment. That's why i-- comes before the alert of the first callback.
A "solution" might be to chain the first of those callback in the second one :
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
console.log(i);
setTimeout(function() {
i--;
DeleteREG(i);
}, 80);
}, 200);
}
}, 400);
})(5);
})();
the functions that are passed to the 2 setTimeouts are created in the same execution scope ( an execution scope is created when a function is executed ) that's why they share the same i variable. The second callback will be fired before the first, therefore altering the i variable.
setTimeout pushes a message into a message queue after x milliseconds have passed, x being the time you passed as the second parameter. Anyway, the callback passed to setTimeout will always run after the current stack has been finished. This happens even if you pass 0 milliseconds ( read more details here).
UPDATE: I'm not sure what are you trying to achieve, but if you want to count from 5 to 1, this would do:
var delay = 1000;
function doStuff (i) {
if ( i > 0 ) {
alert(i);
i -= 1;
setTimeout(function () {
doStuff(i);
}, delay);
}
}
doStuff(5);
Check Out if you're not using throttling options on chrome. It can simulate a slow device, changing timing for intervals.
Related
I have this code from here:
How do I add a delay in a JavaScript loop?
I use it in console in IE, and after this code I call the function with myFunction() in console to run; This first code runs perfectly, it clicks on the second "something" tagnamed element 10 times and between the clicks are 3000 ms delay.
function myFunction() {
(function myLoop (i) {
setTimeout(function () {
document.getElementsByTagName("something")[1].click();
if (--i) myLoop(i); // decrement i and call myLoop again if i > 0
}, 3000)
})(10);
}
I would like to change the number "1" in this code with foor loop, so I want create a code which clicks on elements named "something".
I created this code, but is not working:
for (x=1;x<10;x++){
function myFunction() {
(function myLoop (i) {
setTimeout(function () {
document.getElementsByTagName("something")[1].click();
if (--i) myLoop(i); // decrement i and call myLoop again if i > 0
}, 3000)
})(10);
}
}
If you want to print each element at an interval you need to multiply the timing value with an integer, otherwise all of them will be logged at one time.
Also you may not need to create myFunction inside the loop
for (var x = 1; x < 5; x++) {
(function(i) {
setTimeout(function() {
console.log(i);
}, i * 1000)
}(x))
}
It usually easier to use setInterval rather the a loop with setTimeout. Everything is just simpler:
var count = 10
var intv = setInterval(function(){
if (count === 0 ) {
clearInterval(intv)
console.log("done")
return
}
// do something
console.log(count--)
}, 1000)
But you can recursively call setTimeout:
(function myLoop (i) {
setTimeout(function () {
console.log("loop: ", i)
if (--i) myLoop(i);
}, 1000)
})(10);
Putting the whole thing in a for loop AND calling it recursively is strange though, because the loop will run and make a bunch of individual timeouts that will all run independently, which I don't think is what you want.
function myFunction() {
(function myLoop (i) {
setTimeout(function () {
document.getElementsByTagName("div")[1].click();
if (--i) myLoop(i); // decrement i and call myLoop again if i > 0
}, 3000)
})(10);
}
for (x=1;x<10;x++){
myFunction();
}
<div>1</div>
Try like this. I used div instead of something
So, I'm trying to use create a loop which does this:
setTimeout(function() {
console.log("Hey!");
setTimeout(function() {
console.log("Hey!");
setTimeout(function() {
console.log("Hey!");
}, 1000);
}, 1000);
}, 1000);
So, I tried it like this.
for (i = 0; 1 < 3; i++){
setTimeout(function() {
console.log("Hey!");
}, 1000);
}
How ever, it's not working.
Doing some research I've noticed this is because the timeOuts are getting added to each other with each loop. How can I work around this?
You have to recursively call the time outs, so write a function that takes an argument of the current number of attempts. Have it do an operation, and then call itself with the attempts argument += 1.
You should pass a number of attempts as a safeguard so you can tell the function not to call itself if the attempts number is > some limit, to avoid infinite loops.
Something like:
timedLog(attempts) {
console.log('Hey!');
if (attempts > 10) {
return;
} else {
setTimeout(function() { timedLog(attempts + 1); }, 1000);
}
}
It doesn't look like a for loop anymore, but it's the same principle.
If the output of each function is the same, and you want to print it in the same interval, then you could use setInterval.
function myInterval() {
return setInterval(function(){
console.log("Hey!");
}, 1000);
};
var id = myInterval();
It will repeat forever, so you would have to stop it, in this case, after 3000ms.
setTimeout(function(){
clearInterval(id);
}, 3000);
Just use a loop, increasing the timeout interval each time:
for (let i = 0; 1 < 3; i++){
setTimeout(function() {
console.log("Hey!");
}, i*1000);
}
(Note, that if your callback function depended on i, this won't work as expected if you use var instead of let in the for loop header. The reason is to do with closures - there are many questions about this on SO. But it works perfectly with let - and there are other simple enough fixes if for some reason you can't use let.)
function ShowColoursScreen() {
setSquaresList()
$("#ModeOne").hide();
$("#ModeTwo").show();
setTimeout(function () {
$("#ModeOne").show();
$("#ModeTwo").hide();
setTimeout(function () {
ShowColoursScreen();
}, 1500);
}, 15000);
}
This is very very weird, Im wanting to rotated between two divs every 15 seconds (i dont want to use js intervals). However after the first fifteen seconds ShowColoursScreen(); runs without waiting the second 15 seconds (if that makes sense). Its like the timeout gets ignored, any ideas?
Your code is correct. However, the inner timeout just waits for 1.5 seconds as you forgot a zero. Simply replace the 1500 with 15000.
You can also simplify the call a bit - as you do not have any arguments there is no need for the anonymous function: setTimeout(ShowColoursScreen, 15000);
function ShowColoursScreen($elements) {
if(!$elements instanceof jQuery) {
$elements = $($elements);
}
var current = 0;
// What does this function do?
setSquaresList();
function showCurrent () {
var $currentElement = $($elements[current]);
$elements.not($currentElement).hide();
$currentElement.show();
(current++) % $elements.length;
setTimeout(showCurrent, 15000);
}
showCurrent();
return $elements;
}
ShowColoursScreen('#ModeOne, #ModeTwo')
In this article, the following function is given to perform an operation x times with setInterval()
setIntervalX(function () {
animateColor();
//or something
}, 3000, 4);
function setIntervalX(callback, delay, repetitions) {
var x = 0;
var intervalID = window.setInterval(function () {
callback();
if (++x === repetitions) {
window.clearInterval(intervalID);
}
}, delay);
}
what does the callback() do here? I'm trying to do a function after the specified number of repetitions is complete. but this
setIntervalX(function () {
animateColor();
}, 3000, 4, function(){
completeFunction();
});
does not work. Perhaps that syntax is very wrong. I was under the impression that using jquery, you could string together functions like that..
Much grateful for any insight. Thanks!
I think you misunderstood the description slightly. The setIntervalX performs an interaction x times while you want to have a callback function AFTER the iteration.
function setIntervalX(interationFunction, delay, repetitions, callbackFunction) {
var x = 0;
var intervalID = window.setInterval(function () {
iterationFunction();
if (++x === repetitions) {
callbackFunction();
window.clearInterval(intervalID);
}
}, delay);
}
setIntervalX(
function() {
// this executed every time the interval triggers
},
1000, // amount of milliseconds to delay before interval triggers
5, // amount of repetitions before interval is stopped and callback is executed
function() {
// this will be executed after the interval triggered 5 times
// so after round about 5 seconds after setIntervalX was started
}
);
function setIntervalX(func, delay, times, callback) {
if (times > 0) {
setTimeout(function() {
func.apply(arguments.callee);
setIntervalX(func, delay, --times, callback);
}, delay);
} else {
callback.apply(this);
}
}
setIntervalX(function() {
document.write('ping!<br />');
}, 1000, 5, function() {
document.write('Finished!<br />');
});
I personally prefer the setTimeout method... but that is just me. give this a shot and see if it works. demo
Ahh it appears I have misread you're entire post... so Tobias is correct in his reasoning for your question. mine is an example of what you want.
Wow, much simpler with Frame.js:
for(var i=0; i<4; i++){
Frame(3000, animateColor);
}
Frame(completeFunction);
Frame.start();
Both functions would need to call a callback which is passed to them as the first argument:
function animateColor(callback){
// do stuff
callback(); // to advance to the next interval
}
function completeFunction(callback){
// do stuff
callback(); // to advance to conclude the series of Frames
}
callback in the original function is ran on every interval up to X times. Try this modification to allow for a complete callback:
setIntervalX(function () {
animateColor();
//or something
}, 3000, 4, function(){
alert("all done!");
});
function setIntervalX(callback, delay, repetitions, complete) {
var x = 0;
var intervalID = window.setInterval(function () {
callback();
if (++x === repetitions) {
window.clearInterval(intervalID);
complete();
}
}, delay);
}
I need to flash an element off and on. This works but I don't really like the code. Is there a nice way of doing this?
setTimeout(function(){
toggle();
setTimeout(function(){
toggle();
setTimeout(function(){
toggle();
setTimeout(function(){
toggle();
}, 100);
}, 100);
}, 100);
}, 100);
I'm using jQuery too if that helps.
function toggle_multiple(n)
{
var toggled = 0;
function toggle_one_time()
{
toggle();
toggled += 1;
if (toggled <= n)
setTimeout(toggle_one_time, 100);
}
toggle_one_time();
}
And just call toggle_multiple(4).
A recursive approach:
function multiTimeoutCall (callback, delay, times) {
if (times > 0){
setTimeout(function () {
callback();
multiTimeoutCall (callback, delay, times - 1);
}, delay);
}
}
Usage:
multiTimeoutCall (toggle, 100, 4);
Edit: Yet another approach, without filling the call stack:
function multiTimeoutCall (callback, delay, times) {
setTimeout(function action() { // a named function expression
callback();
if (--times > 0) {
setTimeout (action, delay); // start a new timer
}
}, delay);
}
I could used arguments.callee instead of a named function expression, but seems that it will be deprecated some day in ECMAScript 5...
Why not use setInterval?
var toggler = function() {
if (++self.counter >= self.BLINK_AMOUNT * 2) {
self.counter = 0;
window.clearInterval(self.timer);
return;
}
toggle();
};
toggler.BLINK_AMOUNT = 1;
toggler.counter = 0;
toggler.timer = window.setInterval(toggler, 100);
I can't remember whether or not IE properly implements the self variable in a timer callback - if it doesn't, use a uniquely named global variable instead.
I would use a blinking effect. For jquery there's pulsate, hope that works for you.
Here's yet another version for simplicity:
for (var i= 0; i<4; i++)
setTimeout(toggle, (i+1)*100);
For larger numbers an interval may be more appropriate, but if it's just four toggles multiple timeouts are fine.
Generalizing 'unknown's' idea of using setInterval,
function schedule(fn, max, delay)
{
var counter = 0;
var interval = setInterval(
function()
{
if(counter++ === max)
clearInterval(interval);
fn();
}
, delay);
}
Usage:
schedule(toggle, 4, 100);
If its just flashing that is required, why not use the jQuery animate ? I use the following to direct user attention to messages. But you can do this for any element -
$("#message_box").fadeOut(450).fadeIn(350);
If you want it multiple times, do this -
$("#message_box").fadeOut(450).fadeIn(350).fadeOut(450).fadeIn(350);
You can do like this:
function toggleMany(cnt) {
toggle();
if (--cnt >= 0) window.setTimeout('toggleMany('+cnt+')', 100);
}
toggleMany(4);