事件循环 分析

2020-04-03  本文已影响0人  小本YuDL

1.浏览器常驻线程

2.浏览器的Event Loop

浏览器事件循环的流程

执行上下文 --> 同步压栈执行 -->异步挂起(宏任务/微任务) -->宏任务 -->微任务 -->微任务 ……-->栈空 -->结束

例题分析1

    setTimeout(()=>{
        console.log("setTimeout1")
    },0);
    console.log("window");
    new Promise((resolve,reject)=>{
            console.log("promise");
            setTimeout(()=>{
               console.log('setTimeout2');
                resolve();
            },0);
        })
        .then(()=> {
            console.log("promise1")
        })
        .then(()=>{
            console.log("promise2")
        });
    setTimeout(()=>{
        console.log('setTimeout3');
        new Promise((resolve,reject)=>{
            console.log("promise3");
            resolve();
        }).then(()=> {
           console.log("promise4")
        });
    },0);

执行结果

分析:

3.Node 的 Event Loop

Node的事件循环的流程

外部输入数据 --> 轮询阶段(poll) --> 检查阶段(check) --> 关闭事件回调阶段(close callback) --> 定时器检测阶段(timer) --> I/O事件回调阶段(I/O callbacks) -->闲置阶段(idle, prepare) --> 轮询阶段(按照该顺序反复运行)...

异步队列也分为宏任务与微任务:

例题分析2

const fs = require('fs')
fs.readFile(__filename, () => {
   setTimeout(() => {
       console.log('timeout');
   }, 0)
   setImmediate(() => {
       console.log('immediate')
   })
})

setImmediate 设计在poll阶段完成时执行,即check阶段;
setTimeout 设计在poll阶段为空闲时,且设定时间到达后执行,但它在timer阶段执行
先输出 immediate,在输出timeout。此段代码,写在I/O阶段,先check阶段,队列空闲且计时到点时,在执行timer阶段。

例题分析2

console.log('start')
setTimeout(() => {
  console.log('timer1')
  Promise.resolve().then(function() {
    console.log('promise1')
  })
}, 0)
setTimeout(() => {
  console.log('timer2')
  Promise.resolve().then(function() {
    console.log('promise2')
  })
}, 0)
Promise.resolve().then(function() {
  console.log('promise3')
})
console.log('end')

node执行结果:start=>end=>promise3=>timer1=>timer2=>promise1=>promise2
浏览器执行结果:start=>end=>promise3=>timer1=>promise1=>timer2=>promise2

分析:

总结

浏览器和Node 环境下,微任务队列的执行时机不同

上一篇 下一篇

猜你喜欢

热点阅读