宏任务与微任务的理解

  • 宏任务与微任务是什么?
    • 宏任务与微任务表示异步任务的两种分类
    • 宏任务:包括整体代码script(可以理解为外层同步代码)、settimeout、setInterval、i/o、ui render
    • 微任务:promise、object.observe、MutationObserver(监听DOM树的变化)、process.nextTick
    • 因为异步任务放在队列中,自然而然宏任务与微任务就存放在宏任务队列与微任务队列中
  • 代码的执行顺序:先执行渲染主线程中的同步代码,那异步任务怎样执行的?
    • 先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕(事件循环EventLoop)。
  • 简言之就是放入队列时宏任务、微任务不分优先级,但是将队列中的任务拿到执行栈中执行微任务优先(当微任务队列的所有任务全部执行完后,才开始执行宏任务)
    在这里插入图片描述

相关试题

setTimeout(function() {
    console.log('1');
})
new Promise(function(resolve) {
    console.log('2');
}).then(function() {
    console.log('3');
})
console.log('4');
//打印顺序 2 4 3 1

执行顺序

  1. 遇到setTimeout,异步宏任务将其放到宏任务列表中 命名为time1
  2. new Promise 在实例化过程中所执行的代码都是同步执行的(function中的代码),输出2
  3. 将Promise中注册的回调函数放到微任务队列中,命名为then1
  4. 执行同步任务cosole…log(‘4’) ,输出4,至此执行栈中的代码执行完毕
  5. 从微任务队列取出任务then1到主线程中,输出3,至此微任务队列为空
  6. 从宏任务队列中取出任务time1到主线程中,输出1,至此宏任务队列为空
console.log(1)
setTimeout(function(){
  console.log(2);
  let promise = new Promise(function(resolve, reject) {
      console.log(7);
      resolve()
  }).then(function(){
    console.log(8)
  });
},1000);
setTimeout(function(){
  console.log(10);
  let promise = new Promise(function(resolve, reject) {
      console.log(11);
      resolve()
  }).then(function(){
    console.log(12)
  });
},0);
let promise = new Promise(function(resolve, reject) {
    console.log(3);
    resolve()
}).then(function(){
  console.log(4)
}).then(function(){
  console.log(9)
});
console.log(5)

执行顺序

  • 执行同步任务console.log(1) ,输出1
  • 遇到setTimeout放到宏任务队列中,命名time1
  • 遇到setTimeout放到宏任务队列中,命名time2
  • new Promise 在实例化过程中所执行的代码都是同步执行的(function中的代码),输出3
  • 将Promise中注册的回调函数放到微任务队列中,命名为then1
  • 将Promise中注册的回调函数放到微任务队列中,命名为then2
  • 执行同步任务console.log(5),输出5
  • 从微任务队列取出任务then1到主线程中,输出4
  • 从微任务队列取出任务then2到主线程中,输出9,至此微任务队列为空
  • 从宏任务队列中取出time2(注意这里不是time1的原因是time2的执行时间为0)
  • 执行同步任务console.log(10),输出10
  • new Promise 在实例化过程中所执行的代码都是同步执行的(function中的代码),输出11
  • 将Promise中注册的回调函数放到微任务队列中,命名为then3,至此宏任务time2执行完成
  • 从微任务队列取出任务then3到主线程中,输出12,至此微任务队列为空
  • 从宏任务队列中取出time1,至此宏任务队列为空
  • 执行同步任务console.log(2),输出2
  • new Promise 在实例化过程中所执行的代码都是同步执行的(function中的代码),输出7
  • 将Promise中注册的回调函数放到微任务队列中,命名为then4,至此宏任务time1执行完成
  • 从微任务队列取出任务then3到主线程中,输出8,至此微任务队列为空

练手题

console.log('1');

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')
    })
})
// 1 7 6 8 2 4 3 5 9 11 10 12

再附一张同步任务和异步任务的执行过程
在这里插入图片描述

参考文章:https://juejin.cn/post/6844903512845860872
参考文章:http://www.bugshouji.com/app-index-run?app=search
参考文章:点击查看

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐