【问题标题】:How to terminate endless while loop via setTimeout in Javascript如何通过 Javascript 中的 setTimeout 终止无限循环
【发布时间】:2017-02-22 12:24:35
【问题描述】:

我有一段带有 while 循环的代码,我想通过 setTimeout() 来停止它。但这似乎是一个无限循环,永远不会触发 setTimeout()。如果我删除 while 循环,超时会正确触发。请问有什么问题吗?

$(document).ready(function() 
{
    var i = 0, s = false;

    setTimeout( function()
    {
        s = true;
        console.log( "Timeuot!!!" );
        console.log( "s value is " + s );
    }, 1000 );

    while( s === false )
    {
        console.log( "this is while and s is " + s );
        i++;
    }

    console.log( "iterations: " + i );
});

【问题讨论】:

  • @Quentin s 里面的 setTimeout 是在全局范围内设置的。为什么我错了?
  • @RoyiNamir — 传递给 setTimeout 的函数在另一个函数中定义。它可以访问该函数的范围。由于该范围内有一个非全局的s,因此它会访问该s
  • @RoyiNamir h s 在 setTimeout 中是封闭范围之一,因此在上面声明并定义了几行。
  • @Quentin 哦,伙计,你是对的。我的错。删除。

标签: javascript while-loop


【解决方案1】:

如前所述,while 循环阻塞了唯一的线程。要让您的示例做您想做的事情,请将 while 循环替换为 setInterval(function),如下所示:

$(document).ready(function() 
{
    var i = 0, s = false;

    setTimeout( function()
    {
        s = true;
        console.log( "Timeout!!!" );
        console.log( "s value is " + s );
    }, 1000 );


    var interval = setInterval(function() {
      console.log( "this is while and s is " + s );
      i++;      
      if (s) {
        clearInterval(interval);
        console.log("i is " + i)
      }
    }, 100);    
});

【讨论】:

    【解决方案2】:

    JavaScript 运行单个事件循环。它不会在函数中间停下来查看是否有任何事件(如点击或超时)会触发不同的函数。

    简而言之:在 while 循环完成之前,它不会运行定时函数。


    要执行此类操作,您通常需要一个事件驱动的迭代器。

    var i = 0,
      s = false;
    
    setTimeout(function() {
      s = true;
      console.log("Timeuot!!!");
      console.log("s value is " + s);
    }, 1000);
    
    next();
    
    function next() {
      if (s) {
        return done();
      }
      console.log({
        s, i
      });
      i++;
      setTimeout(next, 0);
    }
    
    function done() {
      console.log("iterations: " + i);
    }

    【讨论】:

    • 嗯。但它确实停止并表明它不是无限循环。jsbin.com/cewewarovo/1/edit?html,js,console,output
    • @RoyiNamir — JSbin 似乎会破坏代码以阻止人们使用它进行 DOS 攻击。 while (s === false) {if (window.runnerWindow.protect.protect({line: 13}))break;window.runnerWindow.proxyConsole.log("this is while and s is " + s);i++;} — 它在其中添加了一个 break
    • 感谢您的澄清
    【解决方案3】:

    setTimeout 永远不会被调用,因为 while 永远不会结束,因此偶数调度程序不会触发 setTimeout。

    【讨论】:

      猜你喜欢
      • 2021-06-30
      • 2011-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      相关资源
      最近更新 更多