事件循环(Event loops)运行机制

134 阅读2分钟

宏任务

JS的主线程,代码由上而下执行,包含

  • 整体的同步代码
  • settimeout(异步函数)
  • setinterval (异步函数)

微任务

  • process.nextTick(node.js版的"setTimeout")
  • promise
  • async-await

微任务优先级

node中存在优先级:process.nextTick()>Promise.then()>setImmediate。

执行过程

  1. 由上而下执行代码,
  2. 碰到宏任务的异步函数,将其回调函数注册并存放宏任务队列中,
  3. 碰到微任务的异步函数,将其回调函数注册并存放微任务队列中,(promise会立即执行除了回调函数.then、.catch的同步代码,因为new promise()是一个同步的过程,实例化对象)
  4. 等到宏任务执行完毕,再去微任务队列中按顺序执行微任务,
  5. 执行微任务的过程中,如果有新的微任务产生,会把新的微任务放到微任务队列中,
  6. 当微任务队列中的所有微任务(包括新的)执行完毕以后,一轮事件循环就结束了,
  7. 新的一轮事件循环就开始了,按顺序执行宏任务队列中的宏任务,并执行其对应的微任务,(即宏任务队列中有10个宏任务等待执行,需要先执行第一个宏任务及其对应的微任务,才会执行第二个宏任务)

关于async await 需要注意的地方

  • 情况1:假如await后边跟的是一个变量,则在执行完await的函数内容之后,会直接将后边的函数注册成为一个微任务
  • 情况2:假如await后边跟的是一个异步函数,则在执行完await的函数内容之后,会跳出当前的async函数,执行其他的任务,当所有的任务完成再回来进行await后边的任务。
  • 具体参考:https://juejin.cn/post/6844904079353708557

Snipaste_2021-12-09_17-25-47.png

测试题


setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

Snipaste_2021-12-09_18-08-32.png