1

clipboard.png

浏览器三个常驻线程

浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:

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单线程)。


sdbxpjzq
150 声望3 粉丝

人生就像写代码,每一次成长就是一次更新,每一次收获就是一个迭代。所以...得写好代码,写好人生(就算现在写不出好的代码,可至少有一颗迭代的心),付出才可能有回报。