setInterval within a for-loop not working - javascript

What I want is an infinite loop that alerts 1, 2, 3, 1, 2, 3, ... with an interval of 2000 milliseconds. But it's not working. The console's not showing any error though. What's the problem here?
for (i = 1; i <= 3; i++) {
setInterval(function() {
alert(i);
}, 2000);
if (i == 3) {
i = 0;
}
}

This will do:
var i = 0;
setInterval(function () {
i += 1;
if (i == 4) {
i = 1;
}
alert(i);
}, 2000);
I've checked it chrome too.
It outputs 1,2,3,1,2,3... as you have requested.

you can not setInterval() inside a for loop because it will create multiple timer instance.
The setInterval() method calls a function or evaluates an expression at specified intervals (in milliseconds).
The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.
The ID value returned by setInterval() is used as the parameter for the clearInterval() method.
Tip: To execute a function only once, after a specified number of milliseconds, use the setTimeout() method.
var i = 0
function test() {
i = i % 3;
++i;
alert(i);
};
setInterval('test()', 2000);

You would not need a loop for this, an interval already goes on infinitley. Try this instead:
var i = 1;
setInterval(function() {
alert(i);
i++;
if(i > 3) {
i = 1;
}
}, 2000);

The reason why this is not working is because you enter the infinite loop in a blocking state, meaning that the interval is never entered as the browser is busy looping. Imagine the browser can only do one thing at a time, as in a single thread, so the loop is it, and cannot do anything else until it's done, and in your case it never is, therefore the interval is waiting for it's turn, which it never gets.
You could make it none blocking like this:
function recursion () {
for (var i = 1; i < 4; i++) {
var num = i;
setInterval(function() {
console.log(String(this));
}.bind(num), 2000);
}
recursion ();
}
recursion ();

my best suggestion is . use event monogramming righterthen loop ,
first make a function then after completing of setInterval call to next function and so on.. that's how u can solve this p

Related

Why is my setTimeout function not waiting for the time specified?

I have a for loop and I want to print its i'th value after a delay but with setTimeout() function, it waits for specified time but then every value of i prints without any delay. Is this because setTimeout() is an Async function and by the time it completes its first countdown, the time for all other values is also over.
for(let i=0;i<10;i++){
setTimeout(()=>{
console.log(i);
},10);
}
OUTPUT:
(10ms Gap) 1-2-3-4-5
OUTPUT REQUIRED: 1 - 10ms Gap - 2 -10ms Gap--... So on. Kindly provide the reason for solution.
You are repeatedly calling setTimeout() in your loop, if you just want to delay your loop, you could try something like this.
loopWithDelay();
async function loopWithDelay() {
for(let i = 0; i < 10; i++){
console.log(i)
await delay(100);
}
}
var timer;
function delay(ms) {
return new Promise((x) => {
timer = setTimeout(x, ms);
});
}
You are correct that the setTimeout is asynchronous, therefore every console.log(i) is set to run at basically the same time. I find it easier to use setInterval in your scenario:
let i = 0;
let myInterval = setInterval(() => {
console.log(i);
i++;
if (i === 10) {
clearInterval(myInterval);
}
}, 10);
You can modify the timer in the loop for every item.
for(let i=0;i<10;i++){
setTimeout(()=>{
console.log(i);
},10*(i+1));
}
This ensures proper gap between every item.
I hope it helps.
Yes, setTimeout() is an async function and all the countdowns start at almost the exact time because there is no waiting time between succesive setTimeout() calls.
What you can do in order to get the expected behaviour is put the for in a function and call that function back from setTimeout() when the countdown runs out:
function f(i) {
if(i < 10) {
setTimeout(()=> {
console.log(i);
f(i+1);
}, 10);
}
}
f(0);

Javascript while setTimeout [duplicate]

This question already has answers here:
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 6 years ago.
I want to make a GreaseMonkey script. I want to have a setTimeout at the end of my while, but I don't know how to do that.
run();
function run(){
var klovas = document.getElementById("light").innerHTML;
var btn = document.getElementsByClassName("farm_icon farm_icon_a");
if(klovas < 6){
alert("Kevés egység van");
} else {
var i = 0;
while (i < btn.length){
if(typeof btn[i] != "undefined"){
btn[i].click();
}
i++;
setTimeout("run()", 3000);
}
}
}
With this code, the problem is that the setTimeout is not working and doesn't wait 3 seconds like it is supposed to.
I tried other ways, but nothing has worked.
EDIT
function run(){
var klovas = document.getElementById("light").innerHTML;
var btn = document.getElementsByClassName("farm_icon farm_icon_a");
if(klovas < 2){
alert("Kevés egység van");
} else {
var i = 0;
while (i < btn.length){
if(typeof btn[i] != "undefined"){
btn[i].click();
}
i++;
}
}
}
setInterval(run, 6000);
I tryed this. Its runing every 6 sec, but i get error in website, that i cand click more than 5 times in a sec. So waiting 6secound when i open the page, and after click, and i get error. Its not jet working. :(
If you wanted it to only trigger once:
function run(){
var data = [1,2,3];
var i = 0;
while (i < data.length) {
console.log(data[i]);
i++;
}
}
setTimeout(run, 3000);
The way you wrote it now, it would repeat every 3 seconds.
function run(){
var data = [1,2,3];
var i = 0;
while (i < data.length) {
console.log(data[i]);
i++;
}
setTimeout(run, 3000);
}
run();
But setInterval would accomplish the same results.
function run(){
var data = [1,2,3];
var i = 0;
while (i < data.length) {
console.log(data[i]);
i++;
}
}
setInterval(run, 3000);
EDIT
User wanted to see what would happen if you call setInterval from inside the callback function. Note that the number of intervals grows exponentially every 3 seconds.
setInterval causes the function to run every 3 seconds, while setTimeout causes the function to run once in 3 seconds.
var numberOfIntervals = 0;
function run(){
setInterval(run, 3000);
numberOfIntervals++;
console.log(numberOfIntervals);
}
run();
There are a few problems here.
Firstly, while setTimeout can accept a function as its first argument, you would want to pass the function as an argument, not execute the function, so you should replace "run()" with run.
Secondly, I'm not exactly sure why you're recursing -- why is setTimeout inside run()? Instead of putting it inside your run function, try putting it at the bottom, and deleting the run() call at the top. As far as I can tell, there's no reason that this code needs to recurse at alll.

Why setInterval wont stop?

Why console.log(1) gets executed here forever:
var interval = setInterval(function() {
if (true) {
clearInterval(interval);
console.log(1);
}
}, 100);
It depends on the scope within which you're executing this code.
If interval is unique within its scope — be it global or function scope — then this will work as expected.
If, however, you execute this code within a loop (for example), then you are overwriting interval with some new interval on each iteration, breaking your clearInterval call for all but the very last setInterval call:
for (var i = 0; i < 3; i++) {
var interval = setInterval(function() {
if (true) {
clearInterval(interval);
console.log(1);
}
}, 100);
}
// ^ will give you one single console log entry,
// and two more console log entries per second forever
It's seems that your variable interval is used somewhere again. If I run code you provided it works as expected. I guess user Lightness has given a great explaination of this, also he provided piece of code where "closure problem" is obvious (which caused you problem too). I just want to add extra information. If you want your code inside of loop + setInteval works aparat you can do the following:
for (var i = 0; i < 3; i++) {
var o = {
i: i,
interval: null,
timer: function() {
if (true) {
clearInterval(this.interval);
console.log(this.i);
}
}
};
o.interval = setInterval(o.timer.bind(o), 1000);
}
DEMO
I hope it will be useful for someone.

Why isn't clearInterval working in this code?

There is a function which sets an interval using setInterval(), but even after calling clearInterval(), I can see in the console that the else condition is still running. How can I clear that interval properly?
function increase(old, step, neu) {
var i = 0;
var delay2;
function countUp() {
if (i < 5) {
old += step;
// console.log("increase")
$("#total-price-value").text(old + " dollors");
$("#total-price-value").digits();
i++;
delay2 = setInterval(countUp, 80);
} else {
clearInterval(delay2);
console.log(delay2);
}
}
countUp();
}​
It looks like you're a little confused about the difference between timeouts and intervals. Timeouts fire only once; intervals fire many times. If you're using an interval, you probably only want to set it once (you're setting it every time). If you're using a timeout, you probably want to set it every time (like you're doing).
In order to fix the problem, you'll either want to switch to timeouts (probably the easiest; just a search/replace) or only set the interval once.
For example, here is how one might use setTimeout to count up to five:
var count = 0;
function timeoutFired() {
count++;
if(count < 5) {
setTimeout(timeoutFired, 1000);
}
}
setTimeout(timeoutFired, 1000);
Using timeouts, we don't need to clear to stop it from counting; simply not setting a timeout will prevent it from running again.
Here is how one might use setInterval:
var count = 0;
function intervalFired() {
count++;
if(count >= 5) {
clearInterval(interval);
}
}
var interval = setInterval(intervalFired, 1000);
If you want some code running periodically using intervals to stop, you must call clearInterval. Note that we only call setInterval once, versus setTimeout every time we didn't want it to continue.
Apparently, you have mistaken setInterval for setTimeout. setInterval runs the enclosed function every n milliseconds while setTimeout executes only once after n milliseconds.
I suppose you wanted to "tick until 5" so here's a sample:
function increase(old, step, neu) {
var i = 0;
interval = setInterval(function() {
if (i < 5) {
//do something at this "tick"
console.log(i);
i++;
} else {
//else, stop
clearInterval(interval);
}
},80);
}
increase();

setTimeout in for-loop does not print consecutive values [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I have this script:
for (var i = 1; i <= 2; i++) {
setTimeout(function() { alert(i) }, 100);
}
But 3 is alerted both times, instead of 1 then 2.
Is there a way to pass i, without writing the function as a string?
You have to arrange for a distinct copy of "i" to be present for each of the timeout functions.
function doSetTimeout(i) {
setTimeout(function() {
alert(i);
}, 100);
}
for (var i = 1; i <= 2; ++i)
doSetTimeout(i);
If you don't do something like this (and there are other variations on this same idea), then each of the timer handler functions will share the same variable "i". When the loop is finished, what's the value of "i"? It's 3! By using an intermediating function, a copy of the value of the variable is made. Since the timeout handler is created in the context of that copy, it has its own private "i" to use.
Edit:
There have been a couple of comments over time in which some confusion was evident over the fact that setting up a few timeouts causes the handlers to all fire at the same time. It's important to understand that the process of setting up the timer — the calls to setTimeout() — take almost no time at all. That is, telling the system, "Please call this function after 1000 milliseconds" will return almost immediately, as the process of installing the timeout request in the timer queue is very fast.
Thus, if a succession of timeout requests is made, as is the case in the code in the OP and in my answer, and the time delay value is the same for each one, then once that amount of time has elapsed all the timer handlers will be called one after another in rapid succession.
If what you need is for the handlers to be called at intervals, you can either use setInterval(), which is called exactly like setTimeout() but which will fire more than once after repeated delays of the requested amount, or instead you can establish the timeouts and multiply the time value by your iteration counter. That is, to modify my example code:
function doScaledTimeout(i) {
setTimeout(function() {
alert(I);
}, i * 5000);
}
(With a 100 millisecond timeout, the effect won't be very obvious, so I bumped the number up to 5000.) The value of i is multiplied by the base delay value, so calling that 5 times in a loop will result in delays of 5 seconds, 10 seconds, 15 seconds, 20 seconds, and 25 seconds.
Update
Here in 2018, there is a simpler alternative. With the new ability to declare variables in scopes more narrow than functions, the original code would work if so modified:
for (let i = 1; i <= 2; i++) {
setTimeout(function() {
alert(i)
}, 100);
}
The let declaration, unlike var, will itself cause there to be a distinct i for each iteration of the loop.
You can use an immediately-invoked function expression (IIFE) to create a closure around setTimeout:
for (var i = 1; i <= 3; i++) {
(function(index) {
setTimeout(function() { alert(index); }, i * 1000);
})(i);
}
This's Because!
The timeout function
callbacks are all running well after the completion of the loop. In fact,
as timers go, even if it was setTimeout(.., 0) on each iteration, all
those function callbacks would still run strictly after the completion
of the loop, that's why 3 was reflected!
all two of those functions, though they are defined
separately in each loop iteration, are closed over the same shared global
scope, which has, in fact, only one i in it.
the Solution's declaring a single scope for each iteration by using a self-function executed(anonymous one or better IIFE) and having a copy of i in it, like this:
for (var i = 1; i <= 2; i++) {
(function(){
var j = i;
setTimeout(function() { console.log(j) }, 100);
})();
}
the cleaner one would be
for (var i = 1; i <= 2; i++) {
(function(i){
setTimeout(function() { console.log(i) }, 100);
})(i);
}
The use of an IIFE(self-executed function) inside each iteration created a new scope for each
iteration, which gave our timeout function callbacks the opportunity
to close over a new scope for each iteration, one which had a variable
with the right per-iteration value in it for us to access.
The function argument to setTimeout is closing over the loop variable. The loop finishes before the first timeout and displays the current value of i, which is 3.
Because JavaScript variables only have function scope, the solution is to pass the loop variable to a function that sets the timeout. You can declare and call such a function like this:
for (var i = 1; i <= 2; i++) {
(function (x) {
setTimeout(function () { alert(x); }, 100);
})(i);
}
You can use the extra arguments to setTimeout to pass parameters to the callback function.
for (var i = 1; i <= 2; i++) {
setTimeout(function(j) { alert(j) }, 100, i);
}
Note: This doesn't work on IE9 and below browsers.
ANSWER?
I'm using it for an animation for adding items to a cart - a cart icon floats to the cart area from the product "add" button, when clicked:
function addCartItem(opts) {
for (var i=0; i<opts.qty; i++) {
setTimeout(function() {
console.log('ADDED ONE!');
}, 1000*i);
}
};
NOTE the duration is in unit times n epocs.
So starting at the the click moment, the animations start epoc (of EACH animation) is the product of each one-second-unit multiplied by the number of items.
epoc: https://en.wikipedia.org/wiki/Epoch_(reference_date)
Hope this helps!
You could use bind method
for (var i = 1, j = 1; i <= 3; i++, j++) {
setTimeout(function() {
alert(this);
}.bind(i), j * 100);
}
Well, another working solution based on Cody's answer but a little more general can be something like this:
function timedAlert(msg, timing){
setTimeout(function(){
alert(msg);
}, timing);
}
function yourFunction(time, counter){
for (var i = 1; i <= counter; i++) {
var msg = i, timing = i * time * 1000; //this is in seconds
timedAlert (msg, timing);
};
}
yourFunction(timeInSeconds, counter); // well here are the values of your choice.
I had the same problem once this is how I solved it.
Suppose I want 12 delays with an interval of 2 secs
function animate(i){
myVar=setTimeout(function(){
alert(i);
if(i==12){
clearTimeout(myVar);
return;
}
animate(i+1)
},2000)
}
var i=1; //i is the start point 1 to 12 that is
animate(i); //1,2,3,4..12 will be alerted with 2 sec delay
the real solution is here, but you need to be familiar with PHP programing language.
you must mix PHP and JAVASCRIPT orders in order to reach to your purpose.
pay attention to this :
<?php
for($i=1;$i<=3;$i++){
echo "<script language='javascript' >
setTimeout(function(){alert('".$i."');},3000);
</script>";
}
?>
It exactly does what you want, but be careful about how to make ralation between
PHP variables and JAVASCRIPT ones.

Categories