JS Event Loop(事件循环)
JS是一门单线程的语言,它的异步和多线程的实现是通过Event Loop事件循环机制实现的。
大致由三个部分组成:
- 调用栈(call stack)
- 消息队列(Message Queue)
- 微任务队列(Microtask Queue)
过程:
- Event Loop开始时,从全局开始一行一行执行,遇到函数调用将其压入栈中。被压入的函数叫做帧(Frame)。然后依次按照函数调用顺序入栈出栈。当所有栈中函数执行结束,调用栈清空。
- 异步操作:如fetch、事件回调、settimeout的回调函数会进入消息队列中称为消息。消息会在调用栈清空的时候执行
- 使用Promise、Async/await创建的异步操作会进入微任务队列 中,它会在调用栈被清空的时候立即执行。并且处理期间新加入的微任务也会立即执行
一个举例,包含调用栈、消息队列、微任务队列:
var p = new Promise(resolve => { console.log(4); //① 调用栈0——4 resolve(5) }) function fn1() { console.log(1); } function fn2() { setTimeout(() => { console.log(2); //⑥ 消息队列0——2 }) fn1(); // ② 调用栈1——1 console.log(3); //③ 调用栈2——3 p.then(resolve => { console.log(resolve); //④ 微任务0——5 }).then(() => { console.log(6); //⑤ 微任务1——6 }) } fn2() // 4 1 3 5 6 2
打印结果:
说明:
- 正常执行的①②③步首先处于调用栈中。执行结束以后。
- 开始依次执行微任务队列中的④⑤两步
- 等调用栈和微任务队列中的所有执行结束,开始执行消息队列⑥中的JS代码
因此:可以直接理解为优先级:调用栈>微任务>消息队列