我最近尝试学习网络设计,想用JavaScript做一个简单的图像淡出。我知道jQuery有一种更简单的方法,在解决这个问题一段时间后,我就用了这种方法,但我偶然发现了它,并想弄明白为什么会发生这种情况。
为了分解这个过程,假设我有一张图像,并希望它每0.1秒减少一次不透明度。因此,我使用了一个for循环,并用SetTimeout( fade ,100)调用了一个淡入淡出函数。但这10个循环中的每一个都是同时执行的。我尝试了更简单的方法:
setTimeout(fade,100);
setTimeout(fade,100); ....
即使这样,函数的所有10个实例也会一次执行。那么对于未来的项目:为什么会这样?是否有可能的变通方法?
非常感谢
发布于 2018-06-18 01:19:39
您应该使用setInterval。
setInterval(fade,100);
setInterval用于重复性任务。它将继续运行。确保在完成后清除间隔,以防止内存泄漏。
您正在使用for循环,这不是正确的方法。
假设当前时刻的时间是:0
您运行了一个for循环并创建了5个setTimeouts。创建它需要一些时间,但您不会注意到它。
因此,每个setTimeout应该在100ms之后执行。
但它们在以下位置创建:
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
发布于 2018-06-18 01:22:04
答案是event loop
。要彻底理解此行为,您必须了解事件循环的所有阶段,尤其是如何处理setTimeout
和setInterval
关于事件循环MDN event loop的MDN文章
上升堆栈文章将帮助您清楚地了解事件循环以及微观和宏观任务
rising stack event loop explained
简而言之,所有的setTimeout
都是在循环的同一tick
中处理的。
对于您的情况,setInterval
也要好得多
发布于 2018-06-18 02:08:16
有多种方法可以实现这一点。正如其他人所建议的,您可以使用setInterval
或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>
https://stackoverflow.com/questions/50898795
复制相似问题