浏览器三个常驻线程
浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:
javascript引擎线程
javascript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程
在运行JS程序
GUI渲染线程
GUI渲染线程负责渲染浏览器界面,当页面需要重绘(repaint)
或由于某种操作引发的回流(reflow)
时,该线程就会执行.但是,需要注意的是GUI渲染线程
与javascript引擎线程
是互斥的
,当js引擎
执行时,GUI线程
就会被挂起,GUI更新会被保存在一个队列中,等待js引擎空闲时立即被执行.
事件触发线程
事件触发线程,当一个事件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理
。
参考:
JavaScript可否多线程? 深入理解JavaScript定时机制
到这里, 就要说另一个问题, js的异步问题
setTimeout(...,0)
在js中,我们常常使用setTimeout(function(){},0)
的方式来处理js的异步.
炒个栗子
console.log(1);
setTimeout(function(){console.log(2)},0);
console.log(3);
输出: 1 , 3, 2
不信点我试试setTimeout(..)
并没有把你的回调函数挂在事件循环队列中。它所做的是设 定一个定时器。
当定时器到时后,环境会把你的回调函数放在事件队列中,如果这时候事件循环中已经有 20 个项目了会怎样呢?你的回调就会等待,定时器只能确保你的回调函数不会在指定的 时间间隔之前运行,但可能会在那个时刻运行,也可能在那之后运行,要根据事件队列的 状态而定(PS: 这就是造成定时器不准确的缘由)。
setTimeout(..0)(hack)
进行异步调度,基本上它的意思就是把这个函数插入到当前事件循环队列的结尾处
。
正常情况下javascript都是按照顺序执行的。但是我们可能让该语句后面的语句执行完再执行本身,先执行所有的同步再执行所有的异步.
炒个栗子
for(var i = 0;i < 3;i++){
setTimeout(function(){
alert('知乎');
},0)
alert(i);
}
点我看看
输出: 0 1 2 知乎 知乎 知乎
,
setTimeout第二个参数为0表示立即执行。当使用这个方法的时候,浏览器会另起一个线程,来执行setTimeout里面的函数,而原有的线程继续执行, 待原有线程结束后,在执行后面的线程(js单线程)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。