【问题标题】:Browser freezing while using SetTimeOut in javascript to run a function which updates the UI在 javascript 中使用 SetTimeOut 运行更新 UI 的函数时浏览器冻结
【发布时间】:2020-11-30 16:37:15
【问题描述】:

我正在使用下面提到的代码来调用一个函数(addCard),它将图像添加到网页。浏览器因此而冻结。如果我在 setTimeOut 中调用一个不更新 UI 的简单函数,则浏览器不会冻结。那么,我们不能在 setTimeOut 回调函数中更新 UI。据我所知,浏览器的 javascript 运行时是单线程的。因此,没有单独的 UI 线程。那为什么浏览器会死机?因为回调将在主线程中运行。代码如下:

 while(user.Score > dealer.Score){
        
        setTimeout(function(){addCard(dealer);},2000);
    }

【问题讨论】:

  • 在导致浏览器死机的情况下,您能估计循环执行的次数吗?另外,条件中的变量如何递增?
  • @DelwynPinto 条件中的变量在 addCard 函数中递增,该函数在 setTimeOut 调用中作为回调传递。

标签: javascript settimeout


【解决方案1】:

你陷入了无限循环,因为user.Score > dealer.Score 永远不会是假的。此外,您会得到递归,因为您每 2 秒调用一次相同的函数,这会自行创建递归。浏览器内存不足,卡住了。

【讨论】:

  • 但是,如果我调用一个简单的函数,它将某些内容记录到控制台。那么这个问题就不会发生了。按照这个推理,这也应该冻结浏览器。
【解决方案2】:

浏览器卡死的简单解释是浏览器耗尽资源。

由于addCard(dealer) 函数在 setTimeout() 之外工作,它让我相信超时的实现是原因。最明显的一点是,完成 UI 更新所花费的时间比线程可用的时间要长。并且由于 while 循环将继续执行,最终调用堆栈将填满。这也将解释为什么浏览器冻结而没有抛出任何错误。

您应该能够通过调试代码来确认此行为。但是,我建议您修改逻辑,而不是尝试解决该问题。

【讨论】:

  • addCard() 没有被调用。所以,UI 更新不可能是原因。
  • 嗯,好的。该信息完全改变了问题。没有它,最终走上了不同的路线。
  • 我想我理解了这个问题。循环不断触发调用堆栈上的 setTimeOut。因此,调用堆栈永远不会为空。因此,回调队列中的 setTimeOut 的回调函数永远不会被调用。它导致无限循环。我认为这就是@Or Assayag 在他的回答中想要表达的意思。
  • 虽然这听起来合乎逻辑,但这不是计时器在 javascript 中的工作方式。此外,调用堆栈填充了我的解释,而不是 Assayag 的。 NodeJs 文档对 javascript 中的计时器有很好的解释:nodejs.org/en/docs/guides/event-loop-timers-and-nexttick
猜你喜欢
  • 2016-12-10
  • 2017-05-20
  • 1970-01-01
  • 2012-07-18
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 2019-12-15
相关资源
最近更新 更多