Javascript中的setTimeout在clearInterval()时不会停止。

6

当clearInterval()无法停止计时器时,您该如何停止计时器?

此代码的目的是将数字从0逐渐动画显示到结束(例如,从0动画显示到75%)。 但是,当我调用clearInterval()时,计时器并没有停止:

http://jsfiddle.net/pwYEe/2/

<div id="foo"></div>
<div id="bar"></div>

animate("99%", $("#foo")); // doesnt stop
animate("75%", $("#bar")); // doesnt stop

function loop(clr, clr2, ele, rand, last, delay) {
    clearInterval(clr);
    clearInterval(clr2);
    inloop(clr, clr2, ele, rand, last, delay);

    if (rand >= last) {
        clearInterval(clr);
        clearInterval(clr2);
    }
    else {
        clr2 = setTimeout(function () {
            loop(clr, clr2, ele, rand, last, delay);
        }, 2500);
    }

}
function inloop(clr, clr2, ele, rand, last, delay) {
    ele.html((rand += 1) + "%");

    if (rand >= last) {
        clearInterval(clr);
        clearInterval(clr2);
    }
    else {
        clr = setTimeout(function () {
            inloop(clr, clr2, ele, rand, last, delay);
        }, delay);
    }
}

function animate(end, display) {
    var clr = null;
    var clr2 = null;
    var ele = null;
    var rand = 0;  // initial number
    var last = 99; // last number
    var delay = 5; // inner loop delay

    ele = display;
    ele.html("0%");

    var idx = end.indexOf("%");
    if (idx >=0) {
        end = end.substring(0,idx);
    }
    last = parseInt(end);
    loop(clr, clr2, ele, rand, last, delay);
}
1个回答

14

您可以使用clearTimeout()函数来取消setTimeout()

不要使用clearInterval()函数来取消setTimeout()clearInterval()适用于与setInterval()一起使用。

您的代码还存在一个结构问题。您正在将clr和clr2作为参数传递,并期望修改这些变量的原始值,但实际上没有修改成功。

您可以通过将它们放在一个对象中并像这样传递该对象来解决这个问题:

animate("99%", $("#foo"));
//animate("75%", $("#bar"));

function loop(timers, ele, rand, last, delay) {
    clearTimeout(timers.clr);
    clearTimeout(timers.clr2);
    inloop(timers, ele, rand, last, delay);

    if (rand >= last) {
        clearTimeout(timers.clr);
        clearTimeout(timers.clr2);
    }
    else {
        timers.clr2 = setTimeout(function () {
            loop(timers, ele, rand, last, delay);
        }, 2500);
    }

}
function inloop(timers, ele, rand, last, delay) {
    ele.html((rand += 1) + "%");

    if (rand >= last) {
        clearTimeout(timers.clr);
        clearTimeout(timers.clr2);
    }
    else {
        timers.clr = setTimeout(function () {
            inloop(timers, ele, rand, last, delay);
        }, delay);
    }
}

function animate(end, display) {
    var timers = {clr: null, clr2: null};
    var ele = null;
    var rand = 0;  // initial number
    var last = 99; // last number
    var delay = 5; // inner loop delay

    ele = display;
    ele.html("0%");

    var idx = end.indexOf("%");
    if (idx >=0) {
        end = end.substring(0,idx);
    }
    last = parseInt(end);
    loop(timers, ele, rand, last, delay);
}
​

可用的 jsFiddle:http://jsfiddle.net/jfriend00/PEqeY/


哈哈。我只是拿这个问题作为例子,它使用了 clearInterval: http://stackoverflow.com/a/4424211/325727。我应该不相信互联网上任何我读到的东西。现在看起来很好 http://jsfiddle.net/pwYEe/4/。 - JK.
@JK - 请描述一下 jsFiddle 应该做什么? - jfriend00
@JK - 你的代码也存在结构问题。你正在将clr和clr2作为参数传递,并期望传递给它们的函数可以修改原始值。但是,它们不能这样做。只有通过引用传递的对象或数组才能实现此功能。timerIDs是按值传递的,改变参数不会影响原始值。 - jfriend00
明白了,不需要循环调用setTimeout(loop,2500) - 这就是为什么它会重复的原因。它应该从0%计数到另一个数字,例如75%。更新后的http://jsfiddle.net/pwYEe/5/。 - JK.
该解决方案还可以修改为使用模块模式,并将clr和clr2保留在闭包中,以便它们的值始终在所需位置可用。 - RobG
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接