我正在努力解决javascript异步在单线程浏览器环境中的工作原理。
作为异步,我们可以同时处理定时器和xhr请求。 现在假设我有类似下面的内容
function doStuff() {
for(var i=0; i<100000000; i++) {
// do something to make proc busy
if(i%1000 === 0) {
console.log('in for loop');
}
}
}
setTimeout(function() {
console.log('timed out')
}, 2);
doStuff();
doStuff();
doStuff();
定时器设置为非常小的值(2ms),所以我认为它应该如下工作:
1)计时器回调排队
2)执行doStuff()
(作为一个整体?),需要一些时间(超过2毫秒)
3)运行计时器回调,因为有一个doStuff()
执行和另一个
4)下一个doStuff()
被称为
4)最后doStuff()
被称为
我所看到的是,在计时器回调触发之前,所有三个doStuff()
事都已完成。它比那些2ms长得多。是的,我知道setTimeout
中设置的时间值不能保证。
我的问题是javascript如何执行代码?在调用异步队列的某些内容之前,将立即执行的最小的原子块是什么?
答案 0 :(得分:5)
你错了:
3)运行定时器回调,因为有一个doStuff()执行和另一个
之间的时刻
为什么回答以下问题:
在调用异步队列的某些内容之前,将立即执行的最小的原子块是什么?
JavaScript使用称为事件循环的内容。每个事件循环周期都可以称为“tick”。在每个tick上,解释器检查是否存在要执行的异步回调(例如,超时已经到期的setTimeout
回调)。
所有其他同步操作都在同一刻度内进行。因此,在您的示例中,将在 next 标记中检查计时器是否到期,但是对doStuff
的所有三次调用都在当前标记中执行。这就是为什么传递给setTimeout
的时间值无法保证的原因:没有办法知道在下一个滴答之前需要多长时间,因此我们通常会说回调将“尽快”运行。在setInterval
的情况下,甚至可能会删除一些呼叫;例如,当下一个滴答发生在定义的间隔的两倍之后,回调只运行一次。
答案 1 :(得分:3)
由于Javascript是单线程的,因此只有在解释器空闲时才能处理超时。当您对超时函数进行排队时,解释器仍在处理您的主脚本,并且在完成之前将无法处理超时。
只有在没有代码运行时才会处理 setTimeout
或setInterval
或任何其他异步事件。它们不会中断当前代码。任何阻止运行的javascript代码都会延迟所有事件处理程序的执行。
答案 2 :(得分:0)
WebWorker是Async Javascript的更新解决方案。对于sencha开发人员here是本教程,仍然不依赖于setTimeout