使用 break on click 停止循环

Stop for loop using break on click

我有一个从 1 到 20 的简单循环。我想要做的是使用单击按钮停止循环。我所做的是,我设置了一个条件,即单击按钮时变量 stop 的值将更改为 1,这将触发 break。但是值没有改变。

var stop = 0;
for(let i = 1; i <= 20; i++){
  
  if(stop === 1){
    break;
  }
  
  setTimeout(function(){
    $('ul').append('<li>'+ i +'</li>');
  },i * 500);
}

$('button').click(function(){
    stop = 1;
});
ul li{
  list-style-type: none;
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul></ul>

<br>
<button>stop</button>

20 个 setTimeout 函数在您按下停止按钮之前就已被调用。
解决此问题的众多方法之一是检查正在执行的函数 setTimeout 中的 stop 变量。

var stop = 0;
for (let i = 1; i <= 20; i++){
  setTimeout(function(){
    console.log(stop);
    if (stop !== 1) {
      $('ul').append('<li>'+ i +'</li>');
    }
  },i * 500);
}

$('button').click(function(){
    stop = 1;
});
ul li{
  list-style-type: none;
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul></ul>

<br>
<button>stop</button>


编辑:

你问如何停止for循环。你不能这样写。
这就是我为了 "stop" 与 setTimeout.
的循环而实现的方式 您也可以使用 setInterval(检查 以查看操作方法)。
了解它们之间的区别 here):

var stop = false;

function addNumberAndCallNext(number, max) {
    if (!stop && number <= max) {
        $('ul').append('<li>'+ number +'</li>');
        setTimeout(addNumberAndCallNext.bind(null, ++number, max), 500);
    }
}

addNumberAndCallNext(1, 20);

$('button').click(function(){
    stop = true;
});
ul li {
  list-style-type: none;
  float: left;
  padding-right: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul></ul>

<br>
<button>stop</button>

您可以在没有 jQuery 的情况下尝试下一个代码。 我不推荐使用 --- $('ul').append('<li>'+ i +'</li>'); - 是不好的做法。 真正的方法是在循环之前创建节点。 在此任务中,您可以使用 setIntrval 而不是 setTimout 和 loop

let itemList = (i) => {
    let item = document.createElement('li');
    item.value = i;
    item.textContent = i;
    return item;
}

let list = document.getElementById('list');
let stopButton = document.getElementById('stop');
let i = 0,
    interval;
let reset = () => {
    clearInterval(interval)
}

stopButton.addEventListener('click', () => {
    reset()
});

interval = setInterval(() => {
    list.append(itemList(i))
    i++;
    if (i > 20) reset()
}, 300)
<button id="stop">stop</button>
<br>

<ul id="list"></ul>

问题是整个 for 循环在您甚至有机会按下按钮之前就已执行。 setTimeout 实际上并没有休眠或阻塞,而是放置了一个新事件并在 for 循环中继续。

当您的代码暂时完成 运行ning 时,浏览器及其所有用于超时目的的时钟等只能 运行。没有等同于 sleep() 函数的东西。

也许使用异步函数(ES2015 IIRC,当前所有非 IE 浏览器都应该支持),并等待 util.promisify(setTimeout)(2000) 创建的承诺会更直观。

没有拦截功能。没有睡眠内部代码。所有代码基本上 CPU 上的 运行 并设置 I/O 和异步发生的定时器事件,一旦同步部分已经完成。

JavaScript 出于这个原因是不直观的。但是,一旦您看到可以通过这种方式获得一种性能,您可能会感受到异步性的价值。我的意思是...虽然 JS 代码本身正在执行 DOM 无法被浏览器检查。你不能滚动,你不能点击,鼠标光标本身不会改变它的种类。只有在代码块完成后,浏览器才会处理所有未决事件。

您不能通过单击事件停止 for 循环,因为 JavaScript 是单线程的。循环开始

for(let i = 1; i <= 20; i++){
...

执行时同步运行而不会被事件处理程序中断

它将启动 20 个定时器调用,间隔 500 毫秒执行,并 return 在点击处理程序执行之前进入事件循环。

您可以选择无论如何启动计时器调用并在添加元素之前检查停止标志,或者设置某种异步循环(例如使用 setInterval)来递增 i 变量并在 i 达到最大值或发生点击事件时停止计时器回调。

我会递归地做这个。然后你有两个中断条件 stop 和 count === max.

var stop = false;

var print = function(count, max) {
   setTimeout(function(){
      if(stop){
         return;
      }else if(count === max){
         return;
      }else{
         $('ul').append('<li>'+ count +'</li>');
         return print(++count, max);
      }
   }, 500);
}

$('button').click(function(){
    stop = true;
});

print(0, 20);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul></ul>

<br>
<button>stop</button>