浏览器中的eventLoop 与node中的eventLoop
node11之前是不一样,node11之后,与浏览器一样
js单线程存在的问题
- js是单线程的,处理任务是一件接着一件处理,所以如果一个任务需要处理很久的话,后面的任务就会被阻塞
所以js通过Event Loop事件循环的方式解决了这个问题,在了解事件循环前,我们需要了解一些关键词
什么是stack,queue,heap,event loop
- stack(栈,执行栈):先进后出
- queue(队列,回调队列)先进先出
- heap(堆,一堆代码):存储obj对象
Event Loop的具体流程
- 堆里面有同步和异步的方法
- 这些方法,放到栈里,栈是先进后出的执行
- 同步的话一个一个的执行,碰到异步的方法,也会执行,但是不会执行完,而是先交给webapis处理,多个异步,会形成一个队列,先进先出
等到同步的方法执行完后,把wepapi中的异步方法取出来,放到栈中执行
<script> console.log(1) setTimeout(() => { console.log(2) setTimeout(() => { console.log(3) }, 0) }, 0) setTimeout(() => { console.log(4) }, 0) console.log(5) </script>
上面的代码最后输出1,5,2,4,3,执行过程:
只有console.log(2)执行完成,执行栈再次清空时,才会从回调队列取出console.log(3)
1,输出1,将2push进回调队列
2,将4push进回调队列
3,输出5
4,清空了执行栈,读取输出2,发现有3,将3push进回调队列
5,清空了执行栈,读取输出4
6,清空了执行栈,读取输出3
Macrotask(宏任务)、Microtask(微任务)
- Microtask(微任务)虽然是队列,但并不是一个一个放入执行栈,而是当执行栈请空,会执行全部
Microtask(微任务)队列中的任务,最后才是取回调队列的第一个Macrotask(宏任务)
···
<script>setTimeout(() => { console.log(1) }) Promise.resolve().then(() => { console.log(2) Promise.resolve().then(() => { console.log(3) }) }) Promise.resolve().then(() => { console.log(4) })
</script>
···
上面的执行过程是:
1,将setTimeout给push进宏任务
2,将then(2)push进微任务
3,将then(4)push进微任务
4,任务队列为空,取出微任务第一个then(2)压入执行栈
5,输出2,将then(3)push进微任务
6,任务队列为空,取出微任务第一个then(4)压入执行栈
7,输出4
8,任务队列为空,取出微任务第一个then(3)压入执行栈
9,输出3
10,任务队列为空,微任务也为空,取出宏任务中的setTimeout(1)
11,输出1
async/await
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
等价于
async function async1() {
console.log('async1 start');
Promise.resolve(async2()).then(() => {
console.log('async1 end');
})
}
demo
async function a1 () {
console.log('a1 start')
await a2() //相当于同步,直接打印
console.log('a1 end')
}
async function a2 () {
console.log('a2') //相当于同步,直接打印
}
console.log('script start')
setTimeout(() => {
console.log('setTimeout')
}, 0)
Promise.resolve().then(() => {
console.log('promise1')
})
a1()
let promise2 = new Promise((resolve) => {
resolve('promise2.then')
console.log('promise2')
})
promise2.then((res) => {
console.log(res)
Promise.resolve().then(() => {
console.log('promise3')
})
})
console.log('script end')
打印顺序
script start
a1 start
a2
promise2
script end
promise1
a1 end
promise2.then
promise3
setTimeout
参考
https://juejin.im/post/5a6309...
https://github.com/Advanced-F...
可视化
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。