Javascript 如何停止 setTimeout 循环?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8443151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:02:05  来源:igfitidea点击:

How to stop a setTimeout loop?

javascriptcssextjssettimeout

提问by Gihan Lasita

I'm trying to build a loading indicator with a image sprite and I came up with this function

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

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

so the out put is looks like this

所以输出看起来像这样

http://jsfiddle.net/TTkre/

http://jsfiddle.net/TTkre/

I had to use setBgPosition(); inside else to keep this running in a loop so now my problem is how to stop this loop once I want [load finished]?

我不得不使用 setBgPosition(); 在 else 中保持循环运行,所以现在我的问题是如何在我想要 [加载完成] 时停止这个循环?

回答by T.J. Crowder

setTimeoutreturns a timer handle, which you can use to stop the timeout with clearTimeout.

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

So for instance:

所以例如:

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;
        }
}

So you'd use that as:

所以你可以把它用作:

var stop = setBgPosition();
// ...later, when you're ready to stop...
stop();

Note that rather than having setBgPositioncall itself again, I've just had it set cback to 0. Otherwise, this wouldn't work. Also note that I've used 0as a handle value for when the timeout isn't pending; 0isn't a valid return value from setTimeoutso it makes a handy flag.

请注意setBgPosition,我没有再次调用自己,而是将其设置c0. 否则,这是行不通的。另请注意,我已用作0超时未挂起时的句柄值;0不是一个有效的返回值,setTimeout所以它是一个方便的标志。

This is also one of the (few) places I think you'd be better off with setIntervalrather than setTimeout. setIntervalrepeats. So:

这也是我认为你最好使用setInterval而不是的(少数)地方之一setTimeoutsetInterval重复。所以:

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

Used like this:

像这样使用:

var timer = setBgPosition();
// ...later, when you're ready to stop...
clearInterval(timer);

All of the above notwithstanding, I'd want to find a way to make setBgPositionstop things itself, by detecting that some completion condition has been satisfied.

尽管如此,我还是想找到一种方法来使setBgPosition事情本身停止,通过检测某些完成条件已得到满足。

回答by ThimoKl

I know this is an old question, I'd like to post my approach anyway. This way you don't have to handle the 0 trick that T. J. Crowder expained.

我知道这是一个老问题,无论如何我想发布我的方法。这样你就不必处理 TJ Crowder 解释的 0 把戏。

var keepGoing = true;

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

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

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

function stopLoop() {
    keepGoing = false;
}

回答by VALIKHAN

SIMPLIEST WAY TO HANDLE TIMEOUT LOOP

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

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

回答by Neil Essy

You need to use a variable to track "doneness" and then test it on every iteration of the loop. If done == true then return.

您需要使用一个变量来跟踪“完成度”,然后在循环的每次迭代中对其进行测试。如果 done == true 则返回。

var done = false;

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

setBgPosition(); // start the loop

setTimeout( function(){ done = true; }, 5000 ); // external event to stop loop

回答by Theo

As this is tagged with the extjs tag it may be worth looking at the extjs method: http://docs.sencha.com/extjs/6.2.0/classic/Ext.Function.html#method-interval

由于这是用 extjs 标签标记的,因此可能值得查看 extjs 方法:http: //docs.sencha.com/extjs/6.2.0/classic/Ext.Function.html#method-interval

This works much like setInterval, but also takes care of the scope, and allows arguments to be passed too:

这很像 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 Ext.Function.interval(run,200);
}

var bgPositionTimer = setBgPosition();

when you want to stop you can use clearIntervalto stop it

当您想停止时,您可以使用clearInterval来停止它

clearInterval(bgPositionTimer);

An example use case would be:

一个示例用例是:

Ext.Ajax.request({
    url: 'example.json',

    success: function(response, opts) {
        clearInterval(bgPositionTimer);
    },

    failure: function(response, opts) {
        console.log('server-side failure with status code ' + response.status);
        clearInterval(bgPositionTimer);
    }
});

回答by Pritom

I am not sure, but might be what you want:

我不确定,但可能是你想要的:

var c = 0;
function setBgPosition()
{
    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
        {
            Ext.get('common-spinner').setStyle('background-position', numbers[0] + 'px 0px');
        }
    }
    setTimeout(run, 200);
}
setBgPosition();

回答by Bashirpour

var myVar = null;

if(myVar)
   clearTimeout(myVar);

myVar = setTimeout(function(){ alert("Hello"); }, 3000);