如何停止setTimeout循环?

Gih*_*ita 55 javascript css extjs settimeout

我正在尝试用图像精灵构建一个加载指示器,我想出了这个功能

function setBgPosition() {
   var c = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
       Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c<numbers.length)
        {
            setTimeout(run, 200);
        }else
        {
            setBgPosition();
        }
    }
    setTimeout(run, 200);
}
Run Code Online (Sandbox Code Playgroud)

因此输出看起来像这样

http://jsfiddle.net/TTkre/

我不得不使用setBgPosition(); 在其他内部保持这个循环运行所以现在我的问题是如何我想要[加载完成]后停止此循环?

T.J*_*der 87

setTimeout返回一个计时器句柄,您可以使用它来停止超时clearTimeout.

例如:

function setBgPosition() {
    var c = 0,
        timer = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
        Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c >= numbers.length) {
            c = 0;
        }
        timer = setTimeout(run, 200);
    }
    timer = setTimeout(run, 200);

    return stop;

    function stop() {
        if (timer) {
            clearTimeout(timer);
            timer = 0;
        }
}
Run Code Online (Sandbox Code Playgroud)

所以你用它作为:

var stop = setBgPosition();
// ...later, when you're ready to stop...
stop();
Run Code Online (Sandbox Code Playgroud)

请注意setBgPosition,我没有再次调用自己,而是让它c重新开始0.否则,这不起作用.另请注意,我已将0超时未挂起时用作句柄值; 0不是一个有效的返回值,setTimeout所以它是一个方便的标志.

这也是我认为你会更好的地方之一(setInterval而不是)setTimeout.setInterval重复.所以:

function setBgPosition() {
    var c = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
        Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c >= numbers.length) {
            c = 0;
        }
    }
    return setInterval(run, 200);
}
Run Code Online (Sandbox Code Playgroud)

像这样使用:

var timer = setBgPosition();
// ...later, when you're ready to stop...
clearInterval(timer);
Run Code Online (Sandbox Code Playgroud)

所有上述尽管有,我想找到一种方法,使setBgPosition停止的事情本身,通过检测某些完成条件已经满足.

  • @philosopher - 你不需要“如果”。:-) 我总是把它放在那里,但是“0”(现在)被明确定义为无效的计时器句柄,“clearTimeout”(现在)被明确定义为不会在无效的计时器句柄上抛出任何错误或类似的错误,所以你可以摆脱那个“如果”并保留身体而不改变任何东西。(现在,我也这么做了。)在 `run` 中重新使用 `await`:只需注意两件事: 1. 如果在 `run` 中有 `await`,那么根据定义,`run` 必须是一个 `async` 函数,这意味着它返回一个承诺,这意味着你要返回一个对某些东西的承诺(*[cont'd]* 中的代码 (2认同)

小智 11

我知道这是一个老问题,无论如何我想发布我的方法.这样你就不必处理TJ Crowder所提出的0技巧了.

var keepGoing = true;

function myLoop() {
    // ... Do something ...

    if(keepGoing) {
        setTimeout(myLoop, 1000);
    }
}

function startLoop() {
    keepGoing = true;
    myLoop();
}

function stopLoop() {
    keepGoing = false;
}
Run Code Online (Sandbox Code Playgroud)


小智 6

处理超时循环的最简单方法

function myFunc (terminator = false) {
    if(terminator) {
        clearTimeout(timeOutVar);
    } else {
        // do something
        timeOutVar = setTimeout(function(){myFunc();}, 1000);
    }
}   
myFunc(true); //  -> start loop
myFunc(false); //  -> end loop
Run Code Online (Sandbox Code Playgroud)

  • 如果我错了请纠正我,但逻辑不是颠倒了吗? (2认同)