Reputation: 118
I recently try to learn Webdesign and wanted to do a simple fadeout of an image with JavaScript. I Know there is an easier way with jQuery and after some time with this problem i used that way, but i stumbles across it and want to unterstand why this happens.
To break down the process lets say I have an image and want it to reduce its opacity every 0.1 seconds. Therefore I used a for loop and called a fade function with SetTimeout(fade,100). But every of the 10 loops are executed at the same time. I tried it even more simple with
setTimeout(fade,100);
setTimeout(fade,100); ....
Even then all 10 instances of the funtion get executed at once. So for future projects: why is that and is there a possible workaround?
Thank you very much
Upvotes: 0
Views: 1329
Reputation: 515
If you want to use setTimeout to change opacity for every 100 ms, you can try this
setTimeout(fade,100);
setTimeout(fade,200);
setTimeout(fade,300);
...
or set a timing variable in loop
for(let timing=100,timeing<1000,timing+=100) setTimeout(fade,timing);
The 10 setTimeout function almost start at same time and trigger at every 100ms till 1000ms. Because it is asynchronous function, it doesn't wait for previous command to finish.
Upvotes: 0
Reputation: 2979
There are multiple ways to achieve it. As others have suggested you can use setInterval
or use setTimeout
to call recursively. If you must use for
loop for some reason, that is also possible.
The basic idea is your call to second setTimeout
must be given only after the first execution of fade
function or otherwise increase the timeout period between successive calls to setTimeout
.
//\//\//\// method 1
function fadeRecur() {
var d1 = document.querySelector( ".d1" );
if(d1.style.opacity == '') d1.style.opacity = 1;
//console.log(d1.style.opacity);
if(d1.style.opacity > 0) {
d1.style.opacity -= 0.1;
setTimeout(fadeRecur, 100);
}
}
setTimeout(fadeRecur, 100);
//\//\//\// method 2
var fsi;
function fadeInter() {
var d2 = document.querySelector( ".d2" );
if(d2.style.opacity == '') d2.style.opacity = 1;
// console.log(d2.style.opacity);
if(d2.style.opacity > 0) {
d2.style.opacity -= 0.1;
} else {
clearInterval(fsi);
}
}
fsi = setInterval(fadeInter, 100);
//\//\//\// method 3
function fadeLoop() {
var d3 = document.querySelector( ".d3" );
if(d3.style.opacity == '') d3.style.opacity = 1;
//console.log(d3.style.opacity);
if(d3.style.opacity > 0) {
d3.style.opacity -= 0.1;
}
}
for(var i=1; i<=10; i++) {
setTimeout(fadeLoop, i*100);
}
.d1 {
background-color: rgba(255, 0, 0, 0.5);
}
.d2 {
background-color: rgba(0, 255, 0, 0.5);
}
.d3 {
background-color: rgba(0, 0, 255, 0.5);
}
<div class='d1'>recursive setTimeout</div>
<div class='d2'>single setInterval</div>
<div class='d3'>setTimeout in for loop</div>
Upvotes: 0
Reputation: 675
The answer is the event loop
. To thoroughly understand this behaviour you have to understand all stages of event loop and especially how setTimeout
and setInterval
is handled
MDN article on event loop MDN event loop
Rising stack article will help you in getting a clear understanding of event loop along with micro and macro task
rising stack event loop explained
In nutshell all setTimeout
gets processed in same tick
of the loop.
Also for your case setInterval
is much better
Upvotes: 0
Reputation: 1166
You should use setInterval.
setInterval(fade,100);
setInterval is for a repetitive task. It will keep running. Makes sure you clear interval once you are done to prevent memory leakage.
You are using a for loop, which is not the correct way.
Assume at the current instant the time is: 0
You ran a for loop and created 5 setTimeouts. It takes some time to create this but you can't notice it.
So, each setTimeout should execute after 100 ms.
But they are created at:
1. 0.000000001
2. 0.000000002
3. 0.000000003
4. 0.000000004
5. 0.000000005
And they will call the callback after:
1. 100.000000001
2. 100.000000002
3. 100.000000003
4. 100.000000004
5. 100.000000005
(Just for demonstration)
So, you are not going to notice them and these (setTimeout and setInterval) are not absolute. They make take longer.
Hope it helps. :D
Upvotes: 2