1.浏览器进程
- brower进程 :浏览器的主进程,只有一个
- 插件进程: 对应的插件,可以有多个
- GPU进程 : 最多一个,用于3D绘制等
- 渲染Render进程:又名‘浏览器内核’(
重点)就是一个tab页签,包含所有的绘制,排版,渲染,事件等 - sharedworker进程 : 多个页面共享一个进程
2.渲染render进程下6个线程
- GUI渲染线程
- JS引擎线程
- 事件触发线程
- 定时触发线程
- 异步http请求线程
- wobworker线程
3.浏览器进程与线程的流程图
- 为了防止渲染冲突,gui线程render线程于js引擎线程 不能同时执行,互斥的关系。
- 当需要3d支持时候,启动GPU渲染 优化渲染效率(如上下滚动)
4.JS引擎的执行机制
背景
js是单线程的,代码都是同步执行,执行过程其他代码会阻碍,如大数据量I/O操作。要实现多线程操作,引入了事件循环机制Event Loop,实现代码异步操作,异步的代码交给其他线程处理(事件触发线程,定时触发线程,异步http请求线程),当处理结束后通过事件循环机制,一直从队列中回调执行。
概念:
- 同步任务:标签的代码,都在主线程上执行,一解析就立即调用。也可以算一次宏任务。
- 异步任务:分为 宏任务 和微任务。解析后,根据不同的方法加入不同的任务队列。
- 宏任务 : 是一个队列,先进先出。
- 微任务 : 是一个队列,先进先出。
- 调用栈:代码先解析,然后推到执行栈,执行栈的代码都是同步执行。是后进先出。
核心逻辑
- 解析里面的代码,
- 遇到同步任务会加入执行栈,并立即执行。
- 遇到异步任务会根据不同的方法分别加入"宏任务"和“微任务”。
- 在所有代码执行完后,会优先清空当前所有"微任务"队列。
- 然后执行渲染。再进去下一次事件循环,由于
宏任务
事件循环每次只在宏队列读取一个宏任务执行。
script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)
微任务
每次当前执行栈结束前,清空所有微队列里的任务。
微任务包含:
Promise.then
Object.observe
MutationObserver
process.nextTick(Node.js 环境)
执行流程
重点:每次执行完一个宏任务,都会清空所有微任务。
在同一次执行栈中,微任务会优于宏任务先执行。
- 先执行同步代码(注意第一次执行肯定没有任何异步的宏队列,所以只执行同步的代码,异步的宏任务忽略)
- 执行过程中遇到异步代码放入异步队列(可能有宏任务或微任务,宏只能等下次刷新后才执行一个,微任务可以在执行完同步后直接执行)
- 同步代码执行完后,会先执行刚刚入队的所有微任务。
- 页面进行重新渲染。
- 再执行同步代码,同时如果发现有异步的宏任务,会执行一个。
- 然后再执行2.的步骤一直循环 同步代码 -> 1个宏任务 -> 执行所有微任务 -> 渲染 -> 同步代码 -> 1个宏任务 -> 执行所有微任务 ->
测试代码
Promise.resolve().then(function() {
console.log("Promise A")
});
console.log("111");
setTimeout(() => {
console.log("模拟网络请求6秒");
}, 6000);
setTimeout(() => {
console.log("setTimeout");
}, 0);
console.log("222");
Promise.resolve().then(function() {
console.log("Promise B")
});
//打印内容
//111
//222
//Promise A
//Promise B
//setTimeout
//模拟网络请求6秒
注意:如果是then().then() //则依然在微任务中,不用等待下一次,直接入栈,等待前面所有已入栈的微队列结束后再出栈。
Promise.resolve().then(function() {
console.log("Promise A")
}).then(function() {
console.log("Promise A1")
});
console.log("111");
setTimeout(() => {
console.log("模拟网络请求6秒");
}, 6000);
setTimeout(() => {
console.log("setTimeout");
}, 0);
console.log("222");
Promise.resolve().then(function() {
console.log("Promise B")
});
//打印内容
//111
//222
//Promise A
//Promise B
//Promise A1
//setTimeout
//模拟网络请求6秒