19.从浏览器多进程到JS单线程,JS运行机制全面梳理

本文深入探讨了进程与线程的区别,详细阐述了浏览器多进程架构,特别是渲染进程中的线程间关系。浏览器渲染流程从HTML解析到CSS应用,再到页面绘制,JS引擎线程与GUI渲染线程的互斥关系导致了页面加载可能被阻塞。事件循环机制和宏任务、微任务的概念被解释,揭示了JS执行的内在逻辑。最后通过实例展示了微任务在事件队列中的优先级,帮助理解JS运行机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.区分进程和线程

2.多进程的浏览器

3.浏览器内核中线程之间的关系

4.浏览器渲染流程

5.从Event Loop 谈JS的运行机制

6.事件循环进阶:macrotask 与 microtask

1.区分进程和线程

1-1 进程和线程的定义
  • 进程cpu资源分配的最小单位。
  • 线程是cpu调度的最小单位。
  • 一个程序至少有一个进程,一个进程至少有一个线程。
1-2 进程和线程的区别
  1. 根本区别:进程是cpu资源分配的最小单位,线程是cpu调度的最小单位。
  2. 地址空间:进程有自己独立的地址空间,同一进程的线程共享本进程的地址空间。
  3. 资源拥有:进程之间的资源是独立的,同一进程内的线程共享本进程的资源。
  4. 系统开销:进程执行开销大,线程执行开销小

2.多进程的浏览器

  1. Browser 进程:浏览器的主进程(负责协调、主控)
  2. 第三方插件进程
  3. GPU进程:最多一个,用于3D绘制。
  4. 浏览器的渲染进程(浏览器内核):默认每个Tab页一个进程,互不影响。主要作用为页面渲染、脚本执行、事件处理等。

3.浏览器内核中线程之间的关系

  1. GUI渲染线程
  2. JS引擎线程
  3. 事件触发线程
  4. 定时触发器线程
  5. 异步http请求线程
3-1 GUI渲染线程
  • 负责渲染浏览器界面,HTML(DOM树) =》 CSS(CSSDOM) =>合并DOM树和CSSDOM(render 树) =》 布局 =》 绘制
  • JS引擎线程与GUI渲染线程互斥的,当JS引擎执行时挂起GUI线程,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行
3-2 JS引擎线程
  • 负责解析JavaScript脚本,运行代码。
  • JS引擎线程一直等待着任务队列中任务的到来然后处理,一个Tab页(渲染进程)无论何时都只有一个JS引擎线程在运行JS程序。
  • 由于JS引擎线程与GUI渲染线程互斥的,如果JS执行时间过程会导致页面的渲染不连贯,即渲染加载阻塞。
3-3 事件触发线程
  • 负责控制事件循环。
  • 当JS引擎执行代码块如setTimeOut(或鼠标点击,ajax异步请求)等会将对应任务添加到事件进程中。
  • 当对应的触发时,该线程会把事件添加到待处理队列中的队尾,等待JS引擎的处理。
  • 由于JS是单线程,所以这些待处理队列中的事件都得排队等待JS引擎空闲时处理。
3-4 定时触发器发线程
  • setInterval 与 setTimeout 所在的线程
  • 通过此线程来计时并触发定时,计时完毕后,添加到事件队列中,等待JS引擎空闲后执行。
3-5 浏览器内核(渲染进程)中线程之间的关系
  1. GUI渲染线程与JS引擎线程互斥
  2. JS阻塞页面加载

4.浏览器渲染流程

浏览器渲染流程

5.从Event Loop 谈JS的运行机制

5-1 事件循环机制
  • js 分为同步任务异步任务
  • 同步任务都在主线程上执行,形成一个执行栈
  • 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有结果,就在任务队列中放置一个事件
  • 一旦执行栈中所有的同步任务执行完毕(此时js引擎线程空闲),就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行

6.事件循环进阶:macrotask 与 microtask

console.log('script start');

setTimeout(function() {
    console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
    console.log('promise1');
}).then(function() {
    console.log('promise2');
});

console.log('script end');

输出正确顺序:

script start
script end
promise1
promise2
setTimeout
6-1 任务队列中的两种任务类型
  1. macrotask(宏任务)
  2. microtask(微任务)

macrotask(宏任务)

主代码块、setTimeout、setInterval(事件队列中的每一个事件都是一个宏任务)

  • 可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)
  • 每一个宏任务会从头到尾将这个任务执行完毕,不会执行其它
  • 浏览器为了能够使得JS内部宏队列与DOM任务能够有序执行,会在一个宏队列执行结束后,再下个宏队列执行前,对页面进行重新渲染
宏任务 =》 渲染 =》 宏任务

microtask(微任务)

Promise、process.nextTick

  • 可以理解为在当前宏任务执行结束后立即执行的任务,也就是说,在当前宏任务后,渲染和宏任务之前。
  • 所以它的响应速度相比setTimeOut(setTimeOut是宏任务)会更快,因为无需等渲染
  • 也就是说,在某一个宏任务执行完后,就会将它执行期间产生的所有微任务都执行完毕(渲染前)

总结运行机制

  1. 执行一个宏任务(栈中没有就从事件队列中获取)
  2. 执行过程中如果遇到微任务,就将它添加到微任务队列中
  3. 宏任务执行完毕后,立即执行当前微任务队列中所有的微任务
  4. 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  5. 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件对列获取)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值