javascript是单线程,浏览器非单线程

周二、北京、多云

为什么JavaScript是单线程的却能让ajax异步发送和回调请求,还有setTimeout也看起来像是多线程的?还有non-blocking IO, event loop等概念很不清楚。

Javascript是单线程的。

因为js运行在浏览器中,是单线程的,每个window一个JS线程,既然是单线程的,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码。而浏览器是事件驱动的(Event driven),浏览器中很多行为是异步(Asynchronized)的,会创建事件并放入执行队列中。javascript引擎是单线程处理它的任务队列,你可以理解成就是普通函数和回调函数构成的队列。当异步事件发生时,如mouse click, a timer firing, or an XMLHttpRequest completing(鼠标点击事件发生、定时器触发事件发生、XMLHttpRequest完成回调触发等),将他们放入执行队列,等待当前代码执行完成。

function foo() {
console.log( 'first' );
setTimeout( ( function(){ console.log( 'second' ); } ), 5);

}

for (var i = 0; i < 1000000; i++) {
foo();
}

执行结果会首先全部输出first,然后全部输出second;尽管中间的执行会超过5ms。

异步事件驱动

浏览器中很多行为是异步(Asynchronized)的,例如:鼠标点击事件、窗口大小拖拉事件、定时器触发事件、XMLHttpRequest完成回调等。当一个异步事件发生的时候,它就进入事件队列。浏览器有一个内部大消息循环,Event Loop(事件循环),会轮询大的事件队列并处理事件。例如,浏览器当前正在忙于处理onclick事件,这时另外一个事件发生了(如:window onSize),这个异步事件就被放入事件队列等待处理,只有前面的处理完毕了,空闲了才会执行这个事件。setTimeout也是一样,当调用的时候,js引擎会启动定时器timer,大约xxms以后执行xxx,当定时器时间到,就把该事件放到主事件队列等待处理(浏览器不忙的时候才会真正执行)。

浏览器不是单线程的

虽然JS运行在浏览器中,是单线程的,每个window一个JS线程,但浏览器不是单线程的,例如Webkit或是Gecko引擎,都可能有如下线程:

  • 界面渲染线程
  • 浏览器事件触发线程
  • Http请求线程
  • 来源:前端开发博客

Ajax异步请求是否真的异步?

既然说js是单线程运行的,那么XMLHttpRequest在连接后是否真的异步?
其实请求确实是异步的,这请求是由浏览器新开一个线程请求(见前面的浏览器多线程)。当请求的状态变更时,如果先前已设置回调,这异步线程就产生状态变更事件放到 js引擎的事件处理队列中等待处理。当浏览器空闲的时候出队列任务被处理,JavaScript引擎始终是单线程运行回调函数。javascript引擎确实是单线程处理它的任务队列,能理解成就是普通函数和回调函数构成的队列。

总结一下,Ajax请求确实是异步的,这请求是由浏览器新开一个线程请求,事件回调的时候是放入Event loop单线程事件队列等候处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 首先看下面的代码: 执行结果会首先全部输出first,然后全部输出second;尽管中间的执行会超过5ms。为什么...
    不去解释阅读 277评论 0 2
  • 1、 单线程、任务队列的概念 单线程: JavaScript是一个单线程语言,浏览器只会分配一个javascrip...
    海山城阅读 1,051评论 0 1
  • 从哪说起呢? 单纯讲多线程编程真的不知道从哪下嘴。。 不如我直接引用一个最简单的问题,以这个作为切入点好了 在ma...
    Mr_Baymax阅读 2,821评论 1 17
  • NBN的故事50:大战 时间:9000年2月20日 地点:地球 正当乔治讲得唾沫星子到处飞的时候,门口的警卫突...
    我我了阅读 252评论 1 1
  • 只要有你的地方,便是我此生最好的住处。 等不到天黑,烟火不会太完美。 等不到你来,爱情不会太圆满。 1 “姜小五,...
    梦与七鹿阅读 294评论 0 0