2013-01-16 43 views
2

我试图围绕我的头,了解javascript异步如何在单线程浏览器环境中工作。在浏览器中的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()被执行(作为一个整体?),它需要一些

3)定时器的回调运行时间(多于那些2毫秒),因为这里提供时刻betweet一个doStuff()执行与另一

4)未来doStuff()被称为

4)最后doStuff()被称为

我看到的却是,所有这三个doStuff()事情之前计时器回调火灾完成。而且它比那些2ms的时间要长得多。是的,我知道这个时间值设定在setTimeout不能保证。

我的问题是javascript如何执行代码?什么是在异步队列被调用之前一次执行的最小的原子块?

回答

5

你错在这里:

3)计时器回调运行是有片刻betweet一个doStuff()执行和其他

的原因是在回答以下问题:

什么是在异步队列被调用之前一次执行的最小原子块?

JavaScript使用的东西叫做事件循环。每个事件循环周期都可以称为“滴答”。在每次打勾时,解释器检查是否执行异步回调(例如,在超时已到期的setTimeout回调)。

所有其他同步操作发生在同一个tick中。因此,以您为例,将在下一个勾号中检查计时器是否到期,但在当前的勾号中执行对doStuff的所有三个调用。这就是为什么传递到setTimeout的时间值不能保证:没有办法知道需要多长时间才能进行下一个计时,所以我们通常会说回调将“尽快”运行。在setInterval的情况下,一些呼叫甚至可能被丢弃;例如,当下一个滴答发生两次定义的时间间隔时,回调只运行一次。

3

由于Javascript是单线程的,超时只能在解释器空闲时才能处理。当你排队超时功能时,解释器仍然在处理你的主脚本,并且将不能处理超时直到它完成。

setTimeoutsetInterval或任何其他异步事件将仅在没有代码运行时处理。他们不会中断当前的代码。任何运行的JavaScript代码块都会延迟所有事件处理程序的执行。

0

WebWorker是Async Javascript的更新解决方案。对于sencha开发者here是教程,仍然不依赖于setTimeout