为什么不是setTimeout取消我的循环?
我想知道JavaScript语句(在Chrome的控制台中)可以在一毫秒内增加一个variables的次数,所以我很快就把这个代码片段直接写到了控制台中:
var run = true, i = 0; setTimeout(function(){ run = false; }, 1); while(run){ i++; }
问题是它永远运行。
为什么会发生这种情况,我该如何解决?
这回到了JavaScript 1的单线程本质。 会发生什么是这样的:
- 你的variables被分配。
- 你安排一个函数,设置
run = false
。 计划在当前函数运行之后运行(或者其他任何当前活动的)。 - 你有无尽的循环,并留在当前的function。
- 在永无止境的循环之后( 永远不会 ),
setTimeout()
callback将被执行并且run=false
。
正如你所看到的,一个setTimeout()
方法不会在这里工作。 你可以通过检查while
条件中的时间来解决这个问题,但是这会篡改你的实际测量结果。
1至less为了更实际的目的,你可以把它看作是单线程的。 其实有一个所谓的“事件循环”。 在那个循环中,所有的函数都被排队,直到它们被执行。 如果你排队一个新的function,它被放在队列中的相应位置。 在当前函数完成之后,引擎从队列中获取下一个函数(就引入的定时而言,例如setTimeout()
并执行它。
因此,在每一个时间点,只有一个函数被执行,从而使得执行几乎是单线程的。 事件有一些例外情况,在下面的链接中讨论。
以供参考:
-
https://stackoverflow.com/a/16757582/1169798
这里更详细地解释了类似的情况
-
https://stackoverflow.com/a/2734311/1169798
更深入的描述什么时候JS可以被看作单线程,什么时候没有。
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不执行和阻止。