How to setTimeout inside a loop [duplicate] - javascript

This question already has answers here:
Why is my function call that should be scheduled by setTimeout executed immediately? [duplicate]
(3 answers)
Closed 6 years ago.
Are you trying to set a timeout to run multiple functions with some delay between them? Is the timeout inside of a for loop? Are your functions all firing off at the same time, and not respecting the timeout, or otherwise causing messy behaviour?
It is intuitive, but incorrect to write it like this:
for (var i = 0; i < moves.length; i++) {
setTimeout(chooseOne(moves[i]), i * 1000 + 1000);
}
SOLUTION:
The solution is to pass the i values to the timeout indirectly, like this. Write the loop, call your timeout function inside the loop and pass that function the i value.
function clickedOne() {
for (var i = 0; i < moves.length; ++i) {
myTimeout(i);
}
}
then in a separate function, set the timeout, pass an anonymous function as your first parameter, inside that function I call my chooseOne function and pass it the unique value for each iteration. Now you can write a comma, and provide the second parameter for setTimeout which is your timeout. My timeout is one second times i, so each function will execute one second after the one that precedes it.
function myTimeout(i) {
setTimeout(function() { chooseOne(moves[i]); }, 1000 * i);
}
I actually don't know why this works and the first method does not.

Try this:
var i = 0;
setTimeout(function(){
if(i < moves.length){
chooseOne(moves[i++]);
}
}, i * 1000 + 1000);

Related

How is setTimeout called in a for loop js? [duplicate]

This question already has answers here:
What is the JavaScript version of sleep()?
(91 answers)
Closed 2 years ago.
I am trying to write a for loop that has a delay between running each iteration. I thought Id go about it by using setTimeout() as follows.
Input:
for (let i=0;i<3;i++){
setTimeout(()=>{console.log("hi")},10000)
}
Output:
hi
hi
hi
What seems to be happening is that its waiting 10 seconds and then runs the entire for loop, rather than waiting 10 seconds to run each iteration of the for loop. After the first hi is shown to the console, the other 2 follow instantaneously. Why is this the case, rather than a delayed logging of hi and how can I go about doing this?
You don't call setTimeout() inside a for loop. You replace the for loop with setTimeout():
let loop = 0;
function loop () {
console.log("hi");
x++;
if (x<3) {
setTimeout(loop, 10000);
}
}
loop();
This is the traditional way of doing it. You can use a Promise with async/await in modern js to use the for loop again:
// First we need a promisified setTimeout:
function delay (ms) {
return new Promise((resolve,reject) => setTimeout(resolve,ms));
}
async function test () {
for (let i=0;i<3;i++){
await delay(10000);
console.log("hi");
}
}
test();
Javascript is asynchronous which means your timers start immediately rather than each timer blocking until done, and they all execute after roughly 10s plus a few ticks.
If you want you can try setInterval with a counter to clear it:
var counter = 0;
var interval = setInterval(function(){
console.log("hi");
counter+=1;
if (counter == 3) { clearInterval(interval); }
}, 10000);
You can probably work out an alternative using setTimeout as well.

calling multiple setInterval() functions in js with a loop [duplicate]

This question already has answers here:
setTimeout in for-loop does not print consecutive values [duplicate]
(10 answers)
Closed 5 years ago.
I'm new to javascript and I'm having trouble using the setInterval() function properly.
Basically I want to call a function at different given intervals for different parameters both of which I have in lists.
I have a function called myfunction. I have a list called myparam with all of the variables I want to pass this function. And finally I have a list called myfrequency which is the time in millis that I want between each call of myfunction with the parameter given in myparam. I'm trying something like this but it's not working:
for(i=0;i<myparam.length();i++;){
setInterval(function(){myfunction(myparam[i]);},myfrequency[i]);
}
The result of the above code is that it works only for the last index. myfunction gets called at the correct interval with the correct parameter for ONLY the last value in myparam.
Why does this happen? Is my thinking that setInterval() sets up the calling of a function at an interval incorrect?
Well it's because setInterval has a delay which means when the interval runs
the loop is already been finish
To do that just create another function which will start your interval
function StartInterval(index, frequency) {
setInterval(function(){
myfunction(index);
},frequency);
}
Then inside your loop just call this function and pass something
for(i=0;i<myparam.length;i++){
StartInterval(myparam[i], myfrequency[i])
}
/** set what value you want **/
var myparam = [10,20,30];
var myfrequency = [1000,2000,3000];
function myfunction(index) {
console.log(index);
}
function StartInterval(index, frequency) {
setInterval(function(){
myfunction(index);
},frequency);
}
for(i=0;i<myparam.length;i++){
StartInterval(myparam[i], myfrequency[i])
}

How does setTimeout work? [duplicate]

This question already has answers here:
Calling functions with setTimeout()
(6 answers)
Closed 6 years ago.
-so i am obviously trying to get two functions to run automatically whilst on a timer using setTimeout. However i am not to sure how it works. All i can see when i search it up is it in a function. so how do i have it outside a function?
function ChangeImage() {
if(position < TrafficL.length) {
document.getElementById("myImage").src = TrafficL[position];
position++
}
}
function RestartPos() {
if (position==3)
document.getElementById("myImage").src = TrafficL["position"]
position=0
var setTimeout = (ChangeImage(),1500)
var setTimeout = (RestartPos(),6000)
You sould call setTimeout as a function:
setTimeout(ChangeImage,1500);
setTimeout(RestartPos,6000);
ChangeImage and RestartPos are like variables referencing a function. If you place parentheses behind them means, you are calling them immediately, but you want to call them after a given time.
You can store the value return by setTimeout() in a variable though, but it's only for cancelling the countdown later:
// nothing happens, because the timeout was cancelled in 1.5s
var t = setTimeout(ChangeImage,1500);
clearTimeout(t);

Why does this function not increment the timeout? [duplicate]

This question already has answers here:
setTimeout in for-loop does not print consecutive values [duplicate]
(10 answers)
Closed 7 years ago.
I'm trying to figure out why this script doesn't increment the timeout by i, which is what I'd expect it to do:
for( var i=0; i<10; i++ ){
setTimeout( function(){
console.log( i );
}, i*10 );
}
This just logs 10, ten times. setTimeout should have access to i, as should the function, from what I can tell. Still, it doesn't work as I expect it to.
Here is a fiddle
The issue is that by the time the inner function gets executed, the value of i is 10, that's why you're getting 10, 10 times.
Closures 'close' over variables not over values. This means that the closure (the function inside the setTimeout) has access to the variable at the time it executes no to the value of the variable when the closure was created.
So effectively you are executing the following code:
var i;
for(i=0; i<10; i++ ){
}
// delay 0ms
console.log(i);
// some delay
console.log(i);
// some delay
....
Also remember that JS is a single threaded language, so the first setTimeout can't execute until you "yield", that means that the first function inside the setTimeout only executes when the for loop finishes, it doesn't matter how small a delay you specify in the setTimeout
You need to understand about closure. Here's the solution to your problem:
for( var i=0; i<10; i++ ){
(function(i){
setTimeout( function(){
console.log( i );
}, i*10 );
})(i);
}

is setInterval more likely to occur on time than continuous setTimeout calls [duplicate]

This question already has answers here:
setTimeout or setInterval?
(20 answers)
Closed 8 years ago.
I have these snippets of code that do the same thing but use different approaches - setInterval and continuous setTimeout calls:
function log() {
console.log('fn')
}
//option 1
var forTimes = 10;
var doneTimes = 0;
var interval = setInterval(function(){
if (doneTimes < forTimes) {
log();
doneTimes++;
} else {
clearInterval(interval);
}
}, 100);
//option 2
function timeoutFn() {
if (doneTimes < forTimes) {
log();
doneTimes++;
setTimeout(timeoutFn, 100);
}
}
setTimeout(timeoutFn, 100);
Because of the nature of single-threaded javascript neither setTimeout nor setInterval guarantees functional call witing 100 ms since thread may be busy running an event handler or doing reflow/repaint. I'm wondering if any of them has higher likelyhood of executing handler within the specified time? If so, why? Does setInterval act like setTimeout in that it waits for the specified interval to pass and only after that adds handler to the queue?
setInterval is kind of seen as bad practice these days because you have a function being executed at intervals regardless of whether or not the previous call to the function has completed.
With regards to exact time neither is better or worse really.
The best method would be to do a recursive setTimeout Pattern:
var count = 0;
(function loopsiloop(){
setTimeout(function(){
if(count < 10) {
loopsiloop();
}
++count;
}, 100);
})();

Categories

Resources