Skip to content

浏览器线程 ​

本节目标:理解“浏览器线程”的核心思路,并能把它用于实际开发或面试表达。 一、发生一个事件时,事件及事件处理程序会被放入浏览器的事件队列,事件可归为以下几类: 浏览器事件:window.load、document.DomContentLoaded等 网络请求事件:ajax、websocket 用户事件:单双击、鼠标滚动、调整页面大小等 计时器事件:setTimeout,setInterval

事件处理程序如果是function(){}格式,则里面的this指向绑定事件的dom节点对象,跟e.currentTarget一样(即便是事件委托也一样),如果采用()=>{}格式,this指向的是window 二、事件的执行是异步的。

三、对事件队列的处理(放入及执行)是浏览器的渲染进程(又叫内核进程、render进程)负责,渲染进程分为以下线程: 1.GUI线程 负责把html解析成dom tree,把css解析成css rule,然后把两者结合,形成render tree。然后计算出layout tree放入浏览器内存中供Browser进程显示到界面上; 当界面需要重绘或回流时,该线程会被执行; 该线程与JS引擎线程是互斥的,当JS引擎在执行时,该线程会处于暂停状态。这也就是为什么一段JS代码执行时间比较久时页面会出现空白或卡顿的原因

2.JS引擎线程 又叫JS内核,负责解析和执行JS代码; 当JS引擎执行到事件代码语句时(比如addEventListener),会通知事件线程需要关注XXX事件;

3.事件触发线程 主要负责事件队列的维护 当事件触发时会被事件线程监听到,事件线程把事件处理程序放入到事件队列中,这一过程不会打断JS引擎线程的执行

4.定时器触发线程 setTimeout与setInterval所在的线程; 由于js引擎是单线程的,如果处于阻塞线程状态,则会影响记时的准确性,因此需要单独的线程来计时并触发事件 当到达指定时间时,setTimeout回调代码也会被加入到事件队列,注意是加入事件队列,而不是立即执行,因为如果在队列中还有其他待执行的代码时就不会执行; setInterval的情况更特殊,当到达指定时间时,如果上一次的回调函数还在队列中等待执行,则直接跳过而不做任何操作。

5.异步请求线程 XmlHttpRequest所在线程; 假如不采用单独的线程而是直接使用JS引擎线程,从发出请求到等待服务端给出响应的这段时间,JS引擎就会一直处于运行状态,原本可以继续执行后面的代码的,现在只能等待

四、JS是单线程运行的的、那Worker为何可以达到多线程的效果? 为什么JS是单线程执行的?假如JS是多线程执行的,一个线程要添加DOM、另一个线程要删除DOM,就会乱套,这就像两台电脑不能同时使用同一台打印机一样的道理; 创建WebWorker时,JS引擎线程向浏览器申请了worker专用的线程,worker线程(子线程)与JS引擎线程(主线程)之间通过postMessage Api进行线程间的通讯,可以理解为浏览器给JS引擎线程开了外挂; ShardWorker是浏览器中所有tab标签共享的,每个tab标签都有独立的render进程,所以SharedWorker不属于某个Render进程,而是浏览器开了独立的进程来管理。

本站总访问 — 次