浏览器,多进程
- 主进程
- 网络进程
- GPU进程
- 插件进程
- ……
- 渲染进程(内核)
浏览器内核,多线程
- GUI渲染线程
- JS引擎线程(逐渐独立)
- 定时器触发线程
- 事件触发线程
- 异步http请求线程
- ……
JS线程 & 渲染线程 互斥:由于JS会操作DOM/CSSOM,造成回流/重绘。
JavaScript语言,单线程
JS是一种浏览器的脚本语言,设计的初衷是为了完成简单的用户与页面的交互,通常涉及到操作DOM/CSSOM,多线程操作同一DOM会产生矛盾。
同步与异步
- 同步任务:调用后等待结果返回后,才能执行其他操作
- 异步任务:调用后等待结果的同时,可以执行其他操作(通常是I/O操作,被引擎挂起的)
JS执行机制:执行上下文&执行栈
JavaScript 执行上下文、作用域、this、原型 - 掘金 (juejin.cn)
JS原本是同步的、阻塞的。
执行上下文及栈由JS引擎管理。
异步的实现
异步是目的,实现异步则有多种方法。
例如,在Java中可以创建一个新线程,以多线程的方式实现异步。
但JS是单线程的语言,为了实现异步,由运行环境提供机制与异步方法。
单线程实现异步:事件循环Event Loop
JS运行环境提供的,实现非阻塞/异步的一种机制。
任务队列 + 执行栈
执行过程:
- 同步任务在主线程执行栈执行
- 异步任务交给浏览器处理(各自线程),并将回调加入各自的任务队列task queue
- 同步任务执行完毕后(执行栈清空)
- 从微任务队列获取并执行本轮所有微任务
- 从宏任务队列获取一个并执行后
- 选择性更新渲染
- 循环,直到两个队列都清空
浏览器提供Web API,允许异步地调用函数:
- 异步回调
- 宏任务:定时器、I/O、UI渲染(浏览器规定)
- 微任务:promise.then、await下一行、process.nextTick、MutationObserver(ES6规定)
【区分】JS引擎 & JS运行时
JavaScript只是语言
- 引擎 Engine:V8等(解析并执行JS代码)
- 运行时 Runtime:浏览器、Node.js等(提供API,整合引擎,按事件驱动的方式调度)
参考文章
In depth: Microtasks and the JavaScript runtime environment - Web APIs | MDN (mozilla.org)