setTimeout()工作不正常



这是我的代码

(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);

它们在后的同一时刻被称为2000800ms。这就是为什么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上使用节流选项,请检查。它可以模拟慢速设备,改变时间间隔。

最新更新