突然退出循环

时间:2017-03-02 16:15:21

标签: javascript jquery

让我们想象下面的代码:

function DoSomethingHard(parameter1, parameter2, parameter3){
  // Do Something Hard Here
}

var i;
for(i = 0; i <= stuff.length; i++) {
  // "stuff" is an array
  DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
}

$( "#button_to_cancel" ).click(function() {
  //something to cancel
});
  • 假设数组&#34; stuff&#34;有100个位置,因此for循环将运行 100次,即,它会做什么&#34;做一些艰难的事情&#34; 100次。
  • 我们也要考虑&#34; DoSomethingHard&#34;运行大约需要5秒钟 完全。

我的问题是:如何管理取消&#34; DoSomethingHard&#34;?例如,如果它已经运行了50次,我该如何通过按钮取消后续执行?我的尝试没有成功,它总是最终运行整个循环......

提前致谢:)

7 个答案:

答案 0 :(得分:2)

Javascript是单线程的,for循环执行直到完成。我会做这样的事情以留出时间取消。

function DoSomethingHard(param){
 //do something
}

var i = 0;
var loopInterval = setInterval(function() {
  if (i >= stuff.length) {
    clearInterval(loopInterval);
    return;
  }
  DoSomethingHard(stuff[i]);
  i++
}, 10);

$( "#button_to_cancel" ).click(function() {
  clearInterval(loopInterval);
});

答案 1 :(得分:1)

您可以使用setInterval来调用该功能,当您有点击事件时,您可以clear the intervals

var mytimeout;


var i;
for(i = 0; i <= stuff.length; i++) {
  // "stuff" is an array
  mytimeout = window.setInterval(DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3), 2000);
}

$( "#button_to_cancel" ).click(function() {
  //something to cancel
  window.clearInterval(mytimeout)
});

答案 2 :(得分:1)

我看到的最简单的方式:

function DoSomethingHard(parameter1, parameter2, parameter3){
//Do Something Hard Here
}

var i;
var active = true; //as of now, we want to process stuff
for(i=0;i<=stuff.length;i++){
//"stuff" is an array
if(active){
  DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
}else {
   active = true; //reset active in case we want to run loop again later on
   break;        // break out of loop
}
}

$( "#button_to_cancel" ).click(function() {
  active = false;
 });

答案 3 :(得分:0)

除非使用递归或迭代器而不是循环,否则无法通过单击按钮轻松取消它。 但是当满足某些条件时,您可以使用break;语句取消自身内部的循环。例如,你可以写:

    var result;
    for(i=0;i<=stuff.length;i++){
      result = DoSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
      if (result === 'error' || i === 50) break;
    }

如果结果变为&#39;错误,那么这将结束循环。 (或从函数内部返回的任何其他内容)或当我达到50时。

现在我想起来了,只需按一下按钮就可以了,但它需要更多代码并且效率低下。给我一点时间。 更新:我也不会建议这个ppttern,但它非常灵活:

var exitCondition,
    doSomethingHard = function doSomethingHard(parameter1, parameter2, parameter3){
      // Do Something Hard Here
    },
    i,
    length = stuff.length,
    result;
for (i = 0; i <= length; i++) {
  // "stuff" is an array
  result = doSomethingHard(stuff[i].something1, stuff[i].something2, stuff[i].something3);
  if (exitCondition( result, i )) break;
}

$( "#button1_to_add" ).click(function() {
    exitCondition = function( result, index ) {
        return index === 50;
    });
});
$( "#button2_to_cancel" ).click(function() {
    exitCondition = null;
});

这里的线索是让你在循环中检查退出条件(或多个)并让按钮更新这个条件。

答案 4 :(得分:0)

你需要注意循环是同步的,因为你的功能不是。在下一次迭代开始之前,循环不会等待DoSomethingHard()完成。只需几毫秒DoSomethingHard已被调用超过一百次!并且你的循环结束了,所以本质上break在这里没用。我认为没有语言结构可以帮助

那该怎么办?

你需要决定是否在函数本身做某事创建一个全局标志并检查里面函数

function DoSomethingHard(){
  if(flag50done){
    return;
  }else{
    //do what this fn was meant for
  }
}

您可以点击按钮更改flag50done的值,由于return

,其他操作会停止

如果DoSomethingHard是您无法修改的某些第三方功能,您可以将其包装在另一个函数中说runDecider

   function runDecider(a,b,c){
      //add flag check here
      if(flag50done){
        return;
      }else{
       DoSomethingHard(a, b, c);
      }
   }

并在循环中调用它

var result;
for(i=0;i<=stuff.length;i++){
   result = runDecider(stuff[i].something1, stuff[i].something2, stuff[i].something3);
}

答案 5 :(得分:0)

您无法停止来自UI交互的for循环,因为所有内容都在单个线程中运行,并且您的操作仅在循环完全执行后才会执行。您可以使用setInterval作为@jason p表示。

答案 6 :(得分:0)

我这样解决:

function DoSomethingHard(parameter1, parameter2, parameter3){
    //Do Something Hard

    var timer = window.setInterval(function(){
    var page = $$('.page').data('page');
    console.log("The page is: "+page);
    if(page != 'preview'){
        //Cancel...

        console.log('Aborted');
        clearInterval(timer);
    }
 },1000);
}

也就是说,我改变了范围。而是使用按钮点击,我在用户离开页面时监控,所以取消它。