浏览器进程模型
何为进程?
程序运⾏需要有它⾃⼰专属的内存空间,可以把这块内存空间简单的理解 为进程; 每个应⽤⾄少有⼀个进程,进程之间相互独⽴,即使要通信,也需要双⽅ 同意。
何为线程?
⼀个进程⾄少有⼀个线程,所以在进程开启后会⾃动创建⼀个线程来运⾏ 代码,该线程称之为主线程。 如果程序需要同时执⾏多块代码,主线程就会启动更多的线程来执⾏代 码,所以⼀个进程中可以包含多个线程。
浏览器有哪些进程和线程?
浏览器是⼀个多进程多线程的应⽤程序
浏览器内部⼯作极其复杂。 为了避免相互影响,为了减少连环崩溃的⼏率,当启动浏览器后,它会⾃ 动启动多个进程。
其中,最主要的进程有:
-
浏览器进程 主要负责界⾯显示、⽤户交互、⼦进程管理等。浏览器进程内部会启动多个 线程处理不同的任务。
-
⽹络进程 负责加载⽹络资源。⽹络进程内部会启动多个线程来处理不同的⽹络任务。
-
渲染进程 渲染进程启动后,会开启⼀个渲染主线程,主线程负责执⾏ HTML、CSS、 JS 代码。 默认情况下,浏览器会为每个标签⻚开启⼀个新的渲染进程,以保证不同的 标签⻚之间不相互影响。
渲染主线程是如何⼯作的?
-
在最开始的时候,渲染主线程会进⼊⼀个⽆限循环
-
每⼀次循环会检查消息队列中是否有任务存在。如果有,就取出第⼀个任务 执⾏,执⾏完⼀个后进⼊下⼀次循环;如果没有,则进⼊休眠状态。
-
其他所有线程(包括其他进程的线程)可以随时向消息队列添加任务。新任 务会加到消息队列的末尾。在添加新任务时,如果主线程是休眠状态,则会 将其唤醒以继续循环拿取任务 这样⼀来,就可以让每个任务有条不紊的、持续的进⾏下去了。 整个过程,被称之为事件循环(消息循环)
何为异步?
代码在执⾏过程中,会遇到⼀些⽆法⽴即处理的任务,⽐如:
计时完成后需要执⾏的任务 —— setTimeout 、 setInterval
⽹络通信完成后需要执⾏的任务 -- XHR 、 Fetch
⽤户操作后需要执⾏的任务 -- addEventListener
如果让渲染主线程等待这些任务的时机达到,就会导致主线程⻓期处于 「阻塞」的状态,从⽽导致浏览器「卡死」
渲染主线程承担着极其重要的⼯作,⽆论如何都不能阻塞!
因此,浏览器选择异步来解决这个问题
使⽤异步的⽅式,渲染主线程永不阻塞
JS为何会阻碍渲染?
代码明明是先改变的文本,再进入死循环,为何页面3s后才会改变?
这是因为渲染主线程在执行完h1.textContent = "袁老师很帅"之后重新生成一个渲染任务加入到消息队列,而渲染主线程又去执行delay(3000),从而导致浏览器阻塞3s,3s之后,渲染主线程再去执行渲染任务,从而页面字段改变。
任务有优先级吗?
任务没有优先级,在消息队列中先进先出
但消息队列是有优先级的
根据 W3C 的最新解释: 每个任务都有⼀个任务类型,同⼀个类型的任务必须在⼀个队列,不同类型 的任务可以分属于不同的队列。 在⼀次事件循环中,浏览器可以根据实际情况从不同的队列中取出任务执⾏。 浏览器必须准备好⼀个微队列,微队列中的任务优先所有其他任务执行 html.spec.whatwg.org/multipage/w…
在⽬前 chrome 的实现中,⾄少包含了下⾯的队列:
延时队列:⽤于存放计时器到达后的回调任务,优先级「中」
交互队列:⽤于存放⽤户操作后产⽣的事件处理任务,优先级「⾼」
微队列:⽤户存放需要最快执⾏的任务,优先级「最⾼」