Just like continue is used to break current iteration and proceed with the next, how can I break current iteration within setInterval() in JavaScript and proceed with the next interval without waiting?
var intervalID = window.setInterval( function() {
if(conditionIsTrue) {
// Break this iteration and proceed with the next
// without waiting for 3 seconds.
}
}, 3000 );
You could "simply" (or not so simply) clear the interval, and re-create it:
// run the interval function immediately, then start the interval
var restartInterval = function() {
intervalFunction();
intervalID = setInterval(intervalFunction, 3000 );
};
// the function to run each interval
var intervalFunction = function() {
if(conditionIsTrue) {
// Break this iteration and proceed with the next
// without waiting for 3 seconds.
clearInterval(intervalID);
restartInterval();
}
};
// kick-off
var intervalID = window.setInterval(intervalFunction, 3000 );
Here's a demo/test Fiddle.
Just tested this, and it acts as a continue statement in a loop. For fellow coders finding this now, just use return within the setInterval.
var myRepeater = setInterval( function() {
if(conditionIsTrue) {
return;
}
}, 1000 );
EDIT: To comply with the immediate execution after breaking the current execution of the loop, one could instead do something like so (in theory. And beware of recursion issues if conditionIsTrue stays true):
function myFunction() {
if(conditionIsTrue) {
myFunction();
return;
}
// Interval function code here...
}
var myRepeater = setInterval( myFunction, 1000 );
Related
I am trying to get a function to run 10 times with a pause inbetween each run, yet when I try to it repeats the function infinite times then after 10 times it pauses, and so on. Right now this is the code with the problem:
for(i=0;i<10;i++) {
console.log(i);
interval = setInterval(function() {console.log("Function ran");}, 1000);
}
window.clearInterval(interval);
Console:0123456789Function ran["Function ran" is repeated infinite times after "9"]
interval = setInterval(function() {console.log("Function ran");}, 1000);
This line creates a new interval-instance each time, which means you have created 10 intervals. At the end of the loop interval holds the id of the last interval that was created. Hence that's the only one you're clearing, and the other ones are still running.
To cancel the interval, you need to keep track of how many times the function has been invoked. One way you can do that is as follows:
function pauseAndRepeat(delay, iterations, func) {
var i = 0;
var interval = setInterval(function() {
func();
if(++i === iterations) {
clearInterval(interval);
}
}, delay);
}
Here we have a function that defines a counter (i) in its local scope. Then it creates an interval using a function that checks the counter to see if it should call your function (func) or clear the interval when it is done. interval will have been set when the interval-handler is actually called. In this case the handler is basically a closure since it is bound to the local scope of pauseAndRepeat.
Then you can invoke the function as follows:
pauseAndRepeat(1000, 10, function() {
console.log("Function ran");
});
This will print out Function ran ten times, pausing for a second each time.
setInterval is expected to run forever, on an interval. Every time you call setInterval here, you have a new infinite loop running your function every 10s, and as others have noted you only are canceling the last one.
You may do better with chained setTimeout calls:
var counter = 0;
function next() {
if (counter < 10) {
counter++;
setTimeout(function() {
console.log("Function ran");
next();
}, 1000);
}
}
next();
This chains delayed functions, setting a timeout for the next one after each runs. You can do something similar with setInterval and cancellation:
var counter = 0;
var intervalId = setInterval(function() {
console.log("Function ran");
if (++counter >= 10) {
clearInterval(intervalId);
}
}, 1000);
In both these cases the key issue is that you trigger the next run or cancel the interval within the callback function, not in synchronous code.
How to skip a one step in jquery setInterval function
e.g
<script>
// start updating continuously
var timer, delay = 3000; // time in milli seconds
timer = setInterval(function(){
// do something for each iteration
// I want to do this only once
if(result["pass"]){
$("#test").append("<li>Passed</li>");
}
// do something for each iteration
}, delay);
</script>
how can I skip one or more than one steps to happen if they are happened once.
I want to skip only when it happens once. e.g if the condition is true in 101st iteration then it will not happen in first 100 iterations but if condition is still true in 102nd iteration, it should not happen because it happens in 101st iteration.
Any help would be much appreciated.
<script>
// start updating continuously
var timer, delay = 3000; // time in milli seconds
var alreadyAdded=false;
timer = setInterval(function(){
// do something for each iteration
// I want to do this only once
if(!alreadyAdded && result["pass"]){
$("#test").append("<li>Passed</li>");
alreadyAdded=true;
}
// do something for each iteration
}, delay);
</script>
This is a good example of where you can use a closure. You can create a function that returns a function.
This allows you to declare a variable in the scope of the outer function, which can then be accessed by the inner function.
function getIntervalHandler() {
var hasPassed = false;
return function() {
if(!hasPassed) {
if(result["pass"]){
$("#test").append("<li>Passed</li>");
hasPassed = true;
}
}
};
}
timer = setInterval(getIntervalHandler(), delay);
I've looked at many different solutions to this, none of which worked. I know it has something to do with setTimeout, but I don't know how to implement it properly.
function myfunction()
{
//the function
//wait for 1 second before it can be ran again
}
To clarify: I don't want to call the function at a regular interval, I want to be able to enforce a delay before the function can be called again.
var lastTime = 0;
function myFunction() {
var now = new Date().getTime(); // Time in milliseconds
if (now - lasttime < 1000) {
return;
} else {
lastTime = now;
}
// rest of function
}
You don't need to use setTimeout at all. The following is similar to other answers, but uses a closure to remember the last time the function ran rather than a global variable.
var myFunction = function() {
var lastTime = new Date();
return function() {
var now = new Date();
if ((now - lastTime) < 1000) return;
lastTime = now;
/* do stuff */
};
}());
I think the easiest solution would be to hold a boolean variable and reset it to true after a given delay.
fiddle
HTML
<button id="clickme">click me!</button>
JavaScript
var canGo = true,
delay = 1000; // one second
var myFunction = function () {
if (canGo) {
canGo = false;
// do whatever you want
alert("Hi!");
setTimeout(function () {
canGo = true;
}, delay)
} else {
alert("Can't go!");
}
}
$("#clickme").click(function(){
myFunction();
})
With this, you hold a boolean, canGo, and set it to true. If the function is run, it sets canGo to false and sets a setTimeout() for a time period of delay, in milliseconds. If you try to run the function again, it won't run and will, instead, alert("Can't go!"). This was just for demonstrative purposes; you don't need that part. After delay, canGo will be set to true, and you will be able to once more run the function.
var lastRan = 0;
var myFunction = function() {
var now = Date.now();
if(now-lastRan < 1000) {
return;
}
lastRan = now;
//rest of function
};
You may want to use throttle or debounce from underscore.js
http://underscorejs.org/#throttle
throttle_.throttle(function, wait, [options])
Creates and returns a
new, throttled version of the passed function, that, when invoked
repeatedly, will only actually call the original function at most once
per every wait milliseconds. Useful for rate-limiting events that
occur faster than you can keep up with.
By default, throttle will execute the function as soon as you call it
for the first time, and, if you call it again any number of times
during the wait period, as soon as that period is over. If you'd like
to disable the leading-edge call, pass {leading: false}, and if you'd
like to disable the execution on the trailing-edge, pass {trailing:
false}.
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);
http://underscorejs.org/#debounce
debounce_.debounce(function, wait, [immediate])
Creates and returns a
new debounced version of the passed function which will postpone its
execution until after wait milliseconds have elapsed since the last
time it was invoked. Useful for implementing behavior that should only
happen after the input has stopped arriving. For example: rendering a
preview of a Markdown comment, recalculating a layout after the window
has stopped being resized, and so on.
Pass true for the immediate parameter to cause debounce to trigger the
function on the leading instead of the trailing edge of the wait
interval. Useful in circumstances like preventing accidental
double-clicks on a "submit" button from firing a second time.
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
If you just want to run your function again after a set time, you can use setTimeout and pass it the function to run and the delay period in milliseconds.
function myfunction() {
//the function
//run again in one second
setTimeout(myfunction, 1000);
}
Edited based on poster's comments:
var waiting = false;
var myfunction = function() {
if (!waiting) {
//Run some code
waiting = setTimeout(function() {
waiting = false;
}, 1000);
}
};
I want to backup, delete every item in a list, and append each one after 1 second.
I am trying like this:
var backup = $('#rGallery').html();
$('#rGallery li').remove();
console.log($(backup).filter('li').length); /* it logs like 135 */
$(backup).filter('li').each(function(){
var the = $(this);
var timeout = setTimeout(function(){
console.log(the.html()); /* it logs the html, but all at the same time*/
$('#rGallery').append('<li>'+the.html()+'</li>');
/*return*/
},1000);
});
Its works, items are removed and then append'ed again, problem is that they're all being appended after 1 second. Instead of each one to wait 1 second from the previous one.
What am I missing here?
Because you are telling them all to run in one second, they are not added to some magic queue and wait in line to start counting.
$(backup).filter('li').each(function(index){ //added index here
var the = $(this);
var timeout = setTimeout(function(){
console.log(the.html()); /* it logs the html, but all at the same time*/
$('#rGallery').append('<li>'+the.html()+'</li>');
/*return*/
},1000*(index+1)); //multiplied it here
});
setTimeout isn't blocking; it schedules the timeout, then continues. Therefore the next iteration of each() happens immediately, which schedules the next element for exactly the same time (etc).
You should therefore change your code like such (one approach), which runs the function every 1000ms, adding the next element to backup.
var backup = $('#rGallery li');
var i = 0;
$('#rGallery li').remove();
var interval = setInterval(function () {
if (i === backup.length) {
clearInterval(interval);
} else {
var the = $(backup).eq(i);
$('#rGallery').append('<li>'+the.html()+'</li>');
}
i++;
}, 1000);
I have a setInterval loop. It's set to 3500 milliseconds, like so:-
var loop = setInterval(function() { /*stuff*/ }, 3500);
At one point in 'stuff' if a certain situation occurs, I want to force a new iteration of the loop and NOT WAIT for the 3500 milliseconds. How is that possible? Is it continue or do I just need to frame the process differently?
You could try writing an anonymous self-calling function using setTimeout instead of setInterval:
var i = 0;
(function() {
// stuff
i++;
if (i % 2 == 0) {
// If some condition occurs inside the function, then call itself once again
// immediately
arguments.callee();
} else {
// otherwise call itself in 3 and a half seconds
window.setTimeout(arguments.callee, 3500);
}
})(); // <-- call-itself immediately to start the iteration
UPDATE:
Due to a disagreement expressed in the comments section against the usage of arguments.callee, here's how the same could be achieved using a named function:
var i = 0;
var doStuff = function() {
// stuff
i++;
if (i % 2 == 0) {
// If some condition occurs inside the function, then call itself once again
// immediately
doStuff();
} else {
// otherwise call itself in 3 and a half seconds
window.setTimeout(doStuff, 3500);
}
};
doStuff();
You can use something like this... using setTimeout instead of setInterval...
<script type="text/javascript">
var show;
var done = false;
show = setTimeout(showHideForm, 3500);
function showHideForm() {
// Do something
if(done) {
clearTimeout(show);
show = setTimeout(showHideForm, 2000);
}
}
</script>
clearTimeout takes as argument the handle which is returned by setTimeout.
Use a named function and call it when you want.
var loop = setInterval(loopFunc, 3500);
function loopFunc(){
//do something
}
function anticipate(){
clearInterval(loop); //Stop interval
loopFunc(); //Call your function
loop = setInterval(loopFunc, 3500); //Reset the interval if you want
}
My contrived example:
var time = 3500,
loops = 0,
loop;
(function run(){
var wait = time,
dontwait = false;
if (loops++ == 5) {
loops = 0;
dontwait = 1000;
}
console.log('Interval: ', dontwait || wait);
return loop = setTimeout(run, dontwait || wait);
})();
http://jsfiddle.net/NX43d/1/
Basically, a self-invoking function looping back on a self-calling function, with (!) shorthand variable switching. Nifty.
function looper(t) {
var loop = setInterval(function() {
document.write(s++);
if (mycondition) { // here is your condition
loopagain(200); // specify the time which new loop will do
loop = window.clearInterval(loop); // clear the first interval
return; // exit from this function!
}
}, t);
}
window.onload = looper(1000); // this will have default setInterval function time ans will start at window load!
function loopagain(t) {
looper(t);
}
http://jsfiddle.net/tFCZP/