【问题标题】:setTimeout not calling callback to interrupt while loopsetTimeout 不调用回调来中断 while 循环
【发布时间】:2019-01-15 09:15:22
【问题描述】:

我有一个国际象棋程序,它使用递归 alphaBeta 算法(以及在此之上的一些层)搜索移动。我想在 10 秒后停止搜索(但我尝试用 1 秒使其工作),所以我使用 setTimeout 设置全局标志。

  let timeOut = false;
  let i = 0;

  setTimeout(() => {
    timeOut = true;
    console.log('timeout');
    console.log('timeout');
    console.log('timeout');
    console.log('timeout');
  }, 1000);

  while (i < 1000 && timeOut === false) {
    score = mtdf(pos, i, score)
    console.log('depth:' + i + ', size: ' + tp.size());
    i++;
  }

这肯定会在浏览器中运行,所以我知道 console.log 语句应该在浏览器中打印,但它们不是。未调用回调。请帮忙。

编辑:添加了 timeOut 变量初始化以使其更清晰。另外,对不起,忘记添加 i 初始化(并不是这些声明甚至与问题相关,因为问题是 setTimeout 回调甚至没有被执行......)

【问题讨论】:

  • 您能在控制台中看到任何错误吗?
  • 不,我只看到我 console.log 的所有其他内容,所以我知道 console.log 有效。喜欢depth:1, size: 21

标签: javascript settimeout


【解决方案1】:

setTimeout 将运行您传递给它的函数:

  • 经过指定时间后
  • 经过最短超时时间后
  • 当事件循环不忙于做其他事情时

…以最新的为准。

您不能使用超时来中断您的while 循环。 JavaScript 引擎忙于运行while 循环,无法检查超时队列上是否有任何函数等待运行。

你的函数会在循环结束后JS引擎不再忙时被调用。


不要试图从外部打断你的循环。

在进入while循环之前,记录当前时间。

每次循环时,将当前时间与记录时间进行比较。

如果差值大于您希望允许循环运行的周期,则退出循环

【讨论】:

【解决方案2】:

Javascript 是单线程的,这意味着 setTimeout、setInterval 和 XMLHttpRequest 等“异步”语句的执行在单线程上排队。如果有什么东西阻塞了线程(比如你繁重的 while() 循环)异步语句就会延迟。

请参阅here 以获得更详细的答案

为了使您的代码正常工作,我建议查看时间戳

var t0 = new Date().getTime(), t1 = t0;
while(true)
{
    // do stuff here
    t1 = new Date().getTime();
    if (t1 % 100 === 0) console.log(t1); // [debug ]print something every 100ms
    if (t1 - t0 > 1000) break; // kill the loop after one second

}

【讨论】:

    【解决方案3】:

    setTimeoutasynchronous 意味着程序不会等待setTimeout 完成,代码将继续执行。

    您需要使用Promise 等待setTimout 完成,这样您的代码才能正常运行。

    另外,你的代码的问题还在于变量声明,你没有声明itimeOut变量。

    let timeOut = false;
    
    new Promise((resolve) => {
    
      setTimeout(() => {
        timeOut = true;
        console.log('timeout');
        console.log('timeout');
        console.log('timeout');
        console.log('timeout');
        resolve();
      }, 1000);
    
    }).then(() => {
    
      let i = 0;
      while (i < 1000 && timeOut === false) {
        score = mtdf(pos, i, score)
        console.log('depth:' + i + ', size: ' + tp.size());
        i++;
      }
    
    });

    【讨论】:

    • 你误解了这个问题。 OP 正试图阻止 while 循环运行超过一秒钟。他们并没有试图将它的启动延迟一秒钟。
    • 是的,我明白了。所以我在上一段已经提到问题出在变量上。
    • “是的,我明白了”——那么,那承诺的东西到底是什么。
    • 因为他在循环中使用了timeOut,而timeOut 变量赋值在setTimeout 中使用。他的代码在语义上不正确。 timeOut === false 最后总是为假的条件是什么?最好将其从条件中删除。除非,他想对循环中的 timeOut 变量做一些我们不知道的事情,因此他应该用承诺包装它的原因。
    • 他们希望循环开始。然后他们希望超时运行,将timeOut 设置为false。然后他们希望循环停止,因为timeOutfalse。这根本不可能发生,延迟循环的开始直到执行超时函数并将timeOut设置为false将无法实现。
    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 2017-11-13
    • 2012-07-18
    • 2017-05-01
    • 2015-11-30
    • 2016-07-01
    • 1970-01-01
    相关资源
    最近更新 更多