如何停止setTimeout循环?

我试图build立一个图像精灵的加载指标,我想出了这个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); } 

所以输出是这样的

http://jsfiddle.net/TTkre/

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

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

所以你会使用它:

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

请注意,而不是让setBgPosition再次调用自己,我已经把它设置为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); } 

像这样使用:

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

尽pipe如此,我想通过检测一些完成条件已经满足来find一种使setBgPosition 自己停止的方法。

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

 var keepGoing = true; function myLoop() { // ... Do something ... if(keepGoing) { setTimeout(myLoop, 1000); } } function startLoop() { keepGoing = true; myLoop(); } function stopLoop() { keepGoing = false; } 

您需要使用variables来追踪“完成”,然后在循环的每次迭代中对其进行testing。 如果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 

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

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

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

 clearInterval(bgPositionTimer); 

一个示例用例是:

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

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

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

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

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