在探究event-loop之前,我们得先聊一聊 进程 & 线程
-
进程指的是cpu运行指令和保存上下文所需的时间
-
线程是进程中更小的单位在,指的是一段指令执行所需的时间
-
一个进程可以有一个也可以有多个线程
-
gpu是浏览器的绘制功能,就像一个画笔 css启动gpu
那么浏览器是有什么样的规则或者说属性呢?
浏览器新开一个tab页(属于进程)
- 渲染线程
- http请求线程
- js引擎线程
- 线程之间是可以一起工作的
- 但是渲染线程和引擎线程是互斥的
-
JS是单线程的
优点:
- 节约内存
- 没有锁的概念,节约了上下文切换的时间
-
异步
-
宏任务(macrotask): script , setTimeout ,setInterval, setImmediate, I/O, UI-rendering,
-
微任务(microtask): promise.then(),MutationObserver,process.nextTick() 现在让我们来就来看看event-loop吧
Event-Loop
- 执行同步代码 (这属于宏任务)
- 当执行栈为空,查询是否有异步需要执行
- 执行微任务
- 如果有需要,会渲染页面
- 执行宏任务 (下一次event-loop) 接下来有一段js的代码,看看你是否可以看出来他的顺序是怎么样的
setTimeout(() => {
console.log(2);
new Promise((resolve) => {
console.log(4);
resolve()
setTimeout(() => {
console.log(6);
})
}).then(() => {
console.log(5);
})
}, 1000)
console.log(3`);
如果你最后得出的结论是1、3、2、4、5、6的话恭喜你你已经初步了解了event-loop
接下来是一个困难版本的
async function async1() { //函数声明不管也就是不执行
await async2() //浏览器给await开小灶提速
console.log('saync1 end'); //被await挤入微任务队列
}
async function async2() { //函数声明不管
console.log('saync2 end');
}
async1()
setTimeout(function() {
console.log('setTimeout');
}, 0)
new Promise((resolve) => {
console.log('promise');
resolve()
})
.then(() => {
console.log('then1');
})
.then(() => {
console.log('then2');
})
console.log('end');
如果你最终的结果是这样的话,那么你就完成了对事件循环真谛的探究
start saync2 end promise end saync1 end then1 then2 setTimeout