多个SetTimeouts一起执行

时间:2018-06-17 17:11:05

标签: javascript settimeout

我最近尝试学习网页设计,并希望用JavaScript做一个简单的图像淡出。我知道jQuery有一种更简单的方法,经过一段时间后我就用这种方式解决了这个问题,但是我偶然发现它并且想要解释为什么会发生这种情况。

要打破这个过程,我可以说我有一个图像,希望它每0.1秒减少一次不透明度。因此我使用for循环并使用SetTimeout(淡入淡出,100)调用淡入淡出函数。但是10个循环中的每个循环都是同时执行的。我用

尝试了更简单
setTimeout(fade,100);
setTimeout(fade,100); ....

即使这样,所有10个函数实例也会立即执行。 因此,对于未来的项目:为什么会这样,是否有可能的解决方法?

非常感谢

4 个答案:

答案 0 :(得分:2)

你应该使用setInterval。

setInterval(fade,100);

setInterval用于重复性任务。它会继续运行。一旦完成,请确保清除间隔以防止内存泄漏。

您正在使用for循环,这不是正确的方法。

假设当前时间是:0

您运行了for循环并创建了5个setTimeouts。创建它需要一些时间,但你无法注意到它。

因此,每个setTimeout应在100 ms后执行。

但它们是在:

创建的
 1. 0.000000001
 2. 0.000000002
 3. 0.000000003
 4. 0.000000004
 5. 0.000000005

他们将在以下情况后调用回调:

 1. 100.000000001
 2. 100.000000002
 3. 100.000000003
 4. 100.000000004
 5. 100.000000005

(仅供演示)

所以,你不会注意到它们,而这些(setTimeout和setInterval)不是绝对的。他们需要更长时间。

希望它有所帮助。 :d

答案 1 :(得分:0)

答案是event loop。要彻底了解此行为,您必须了解事件循环的所有阶段,尤其是如何处理setTimeoutsetInterval

关于事件循环的MDN文章 MDN event loop

上升的堆栈文章将帮助您清楚地了解事件循环以及微观和宏观任务

rising stack event loop explained

简而言之,所有setTimeout都在循环的tick处理。

同样适合您的情况setInterval要好得多

答案 2 :(得分:0)

有多种方法可以实现它。正如其他人所建议您可以使用setTimeout或使用for来递归调用。如果由于某种原因必须使用setTimeout循环,那也是可能的。

基本思路是,您必须在第一次执行fade函数后才能调用第二个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>
.dropdown-menu {   position: fixed; }

答案 3 :(得分:0)

如果您想使用setTimeout每100毫秒更改一次不透明度,可以试试这个

setTimeout(fade,100);
setTimeout(fade,200);
setTimeout(fade,300);
...

或在循环中设置时序变量

for(let timing=100,timeing<1000,timing+=100) setTimeout(fade,timing);

10 setTimeout函数几乎同时启动,每100ms触发一次,直到1000ms。因为它是异步函数,所以它不会等待先前的命令完成。