这是我的代码
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
alert(i);
}, 2000);
setTimeout(function() {
i--;
DeleteREG(i);
}, 800);
}
}, 4000);
})(5);
})();
根据代码,它应该在i=5,4,3,2,1
发出警报。但它在i=4,3,2,1,0
发出警报。有人能解释一下为什么它不工作吗?应该对代码进行哪些纠正才能正常工作?以下代码也会发生同样的情况
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
alert(i);
}, 2000);
i--;
DeleteREG(i);
}
}, 4000);
})(5);
})();
请以书面形式向我解释解决方案。如何解决这个问题?
当您调用setTimeout
时,您的代码不会停止。
这里定义的这两个函数:
setTimeout(function stop_() {
alert(i);
}, 2000);
setTimeout(function() {
i--;
DeleteREG(i);
}, 800);
它们在后的同一时刻被称为2000
和800
ms。这就是为什么i--
在第一次回调的alert
之前。
一个"解决方案"可能是将第一个回调链接到第二个回调中:
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
console.log(i);
setTimeout(function() {
i--;
DeleteREG(i);
}, 80);
}, 200);
}
}, 400);
})(5);
})();
传递给2个setTimeout
的函数是在同一执行范围中创建的(执行函数时会创建执行范围),这就是它们共享相同i
变量的原因。第二个回调将在第一个回调之前触发,从而更改i
变量。
setTimeout
在x毫秒后将消息推入消息队列,x是您作为第二个参数传递的时间。无论如何,传递给setTimeout的回调将始终在当前堆栈完成后运行。即使超过0毫秒,也会发生这种情况(请阅读此处的详细信息)。
更新:我不确定你想实现什么,但如果你想从5到1计数,这就可以了:
var delay = 1000;
function doStuff (i) {
if ( i > 0 ) {
alert(i);
i -= 1;
setTimeout(function () {
doStuff(i);
}, delay);
}
}
doStuff(5);
如果您没有在chrome上使用节流选项,请检查。它可以模拟慢速设备,改变时间间隔。