当javascript中的条件变量(全局变量)发生变化时,停止循环

Stop loop when condition variable (global var) changes in javascript

本文关键字:变化 循环 javascript 条件 变量 全局变量      更新时间:2023-09-26

我遇到了一个无法解决的问题。我在javascript中有一个循环,其中要停止的条件变量取决于全局变量。循环开始循环,当我更改全局变量的值时,它永远不会停止。

stop = false;
var i = 0;
while ((stop == false) && (i<100000)){
    console.log("hi-"+i);
    i++;
}

当循环运行时,如果我真的停止=true,它就永远不会停止。我不知道为什么。

知道吗?

谢谢!

JavaScript本质上是单线程的。一旦一个代码块开始运行,它就会在其他任何事情发生之前运行完成。IE将stop设置为true的事件在while循环完成后才会执行。

你需要将你的循环分成几个部分,并单独运行每个部分,允许其他事件发生:

stop = false;
var i = 0;
function loopLogic() {
  var tempStop = i + 500;
  while (i < tempStop) {
    //original processing logic
    console.log("hi-" + i);
    i++;
  }
  if (!stop && i < 100000)
    window.setTimeout(loopLogic, 0);
}
window.setTimeout(loopLogic, 0);

这将函数分解为一次500个的多个块。持续时间为0的setTimeout允许函数立即(几乎)继续,但会将下一个块放在执行链的底部。这允许发生其他事件,因此将允许将stop更新为true

这里有一把小提琴展示了这种方法。

兼容浏览器中可用的另一种方法是WebWorker,但这已经开始超出了这个问题的范围。

您可以尝试使用setInterval。。。。把你需要做的事情放入一个函数中,并每隔一段时间调用它。。。看看这里。。。

http://jsfiddle.net/o5mnb7jv/1/

var stop = false;
var obj = document.getElementById("btn").addEventListener("click", function(){
    stop = true;
});
var interval;
function loop(){
    var result = document.getElementById("result");
    if(!stop){
        result.innerHTML = "Running...";
    }else{
        clearInterval(interval);
        result.innerHTML = "Stopped...";
    }
}
interval = setInterval(loop, 500);

听起来您希望JS是多线程的,但事实并非如此,这使得某些事情非常棒。例如,如果JS是多线程的,下面的操作会怎样?

if (x === 3) {
    alert(x);
}

JS中的答案是"它提醒3",但如果JS是多线程的,那么在if和alert之间就不会有任何东西阻止另一个线程编辑x,所以它就不会定义明确。

通过使用setTimeoutsetInterval调度该函数,您可以将控制权返回到浏览器的事件循环,同时确保某些代码将运行。如果您希望递归的结果是异步的,这也允许您在没有大规模调用堆栈的情况下执行递归。此外,JS获得了一个新功能(生成器和yield关键字),这将使您更容易在中间的某个位置"暂停"一个函数,以便稍后恢复。

做你想做的事情最简单的方法是:

var i = 0, running = true;
function iter() {
    if (running && i < 100000) {
        console.log("hi", i++);
        setTimeout(iter, 0);
    }
}
iter();

你也可以在setTimeout调用中使用非零时间——例如,人类的反应时间大约是200ms,所以如果你只是需要从人类的角度来看它是连续的,那么把0改为100;它会给你的电脑多一点呼吸的空间。

您也可以使用setInterval,但要注意,如果某个CPU密集型函数在一段时间内阻止了其他函数的执行,您将把一堆相同的函数排成一个接一个地执行。当setTimeout线程调用setTimeout时,有一个最小延迟,由setTimeout强制执行;setInterval的情况并非如此(它声称调用之间的平均时间是一致的,但没有声明调用之间的最小或最大延迟)。

为了setInterval,您可能希望在某个时间点后停止间隔。当然,在i上添加if检查会使函数成为一个空函数,它什么都不做,因此不会浪费太多时间,但如果您想取消计划,请捕获setInterval的结果并将其传递给clearInterval