繁体   English   中英

为什么 setTimeout 不取消我的循环?

[英]Why isn't setTimeout cancelling my loop?

我想知道一个 JavaScript 的while语句(在 Chrome 的控制台中)可以在一毫秒内增加一个变量多少次,所以我很快就把这个片段直接写到了控制台中:

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

问题是它永远运行。
为什么会发生这种情况,我该如何解决?

这又回到了 JavaScript 1的单线程特性。 发生的事情几乎是这样的:

  1. 您的变量已分配。
  2. 您安排了一个函数,以设置run = false 该计划目前的功能是运行(或任何其他当前活动)运行。
  3. 你有你的无限循环并留在当前函数中。
  4. 在你的无限循环( never )之后, setTimeout()回调将被执行并且run=false

如您所见, setTimeout()方法在这里不起作用。 您可以通过检查while条件中的时间来解决这个问题,但这会干扰您的实际测量。

1至少出于更实际的目的,您可以将其视为单线程。 实际上有一个所谓的“事件循环”。 在该循环中,所有函数都会排队,直到它们被执行。 如果您排队一个新函数,它会被放置在该队列中的相应位置。 当前功能完成之后,发动机将在下次函数从队列(相对于作为引入的定时,例如,通过setTimeout()并执行它。
结果在每个时间点只执行一个函数,从而使执行几乎是单线程的。 事件有一些例外情况,在下面的链接中进行了讨论。


以供参考:

JavaScript 是单线程的,因此当您处于循环中时,不会执行任何其他操作。

为了保持Chrome的真实速度,而不必不断检索时间来计算速度,您可以尝试以下JS代码:

var start = new Date().getTime()
var i = 0
while(i<1000000)
{
    i++
}
var end = new Date().getTime()
var delta = end-start
var speed = i/delta
console.log(speed + " loops per millisecond")

Javascript 是单线程的,这意味着它一次只按顺序运行一条指令。

与许多其他语言和库一样,事件系统由事件循环处理。 事件循环基本上是一个循环,它在每次迭代时检查队列中的消息,并调度事件。

在 javascript 中(就像在实现这种模式的语言中一样),当堆栈为空时,即所有函数都有返回时,换句话说,在程序代码的末尾,将调用事件循环。

你的“真实”程序在幕后看起来像这样:

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

while(true) {
/*
 * check for new messages in the queue and dispatch
 * events if there are some
 */
  processEvents();
}

因此,永远不会处理来自时钟的消息说超时结束。

关于事件循环的更多信息: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop


当然它有点复杂,请在此处查看这些示例: JavaScript 是否保证是单线程的? ( tl;dr:在一些浏览器引擎中,一些外部事件不依赖于事件循环,一旦发生就会立即触发,抢占当前任务。但 setTimeout 不是这种情况,它只是向队列中添加一条消息并且永远不会立即开火。)

While 循环不访问 setTimeout。 您有设置运行为真的代码,然后它永远不会变为假。

JavaScript 具有单线程,并且在任何地方都有单线程。

我认为这个问题很好: JavaScript 是否保证是单线程的?

当您的代码处于循环中时,其他 ocde 不会执行并阻塞。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM