async/await和promise的(eventloop)任务队列执行顺序?

  • 前言:
    关于js异步执行顺序,宏任务、微任务这些,还有async/await已经有好多人写了。但是每个人都有自己的理解,最主要的是要自己琢磨,学习了一下,谈谈自己的理解。

先上一张图压压惊!!!
在这里插入图片描述

微任务与宏任务区别,纯白话理解:

这个就像是去银行办理业务,得先排队取号。我们可以把每个办理业务的人当做是一个宏任务的存在。那么多个宏任务合在一起,可以说这就是一个任务队列。
那么微任务是什么呢?一个宏任务在执行的过程中,是可以添加一些微任务的。
那么微任务是什么呢?举个例子:
就像在柜台办理业务,你前边的一位老大爷可能在存款,在存款这个业务办理完以后,柜员会问老大爷还有没有其他需要办理的业务,这时老大爷想了一下:“要理财,我要发财,哈哈”,然后告诉柜员说,要办一些理财的业务,这时候柜员肯定不能告诉老大爷说:“您再上后边取个号去,重新排队吧”。
所以本来快轮到你来办理业务,会因为老大爷临时添加的“理财业务”而往后推。而这些临时发生的我们可以认为就是微任务!
再次说明:你大爷永远是你大爷!吼吼 在当前的微任务没有执行完成时,是不会执行下一个宏任务的。所以就有了以下类似面试题:

setTimeout(()=>{
      console.log('1');
    },0) // 放置任务队列 -- 宏任务 
    new Promise((resolve, reject)=>{
    console.log('2');
     // 同,这里注意promise是用来管理异步操作,本身非异步
      reject() // 结果回调
    }).then(value=> { // 微任务
      console.log('3');
    }, reason => {
      console.log('5');
      setTimeout(()=> {
        console.log('6');
      })
    })
    console.log('4');
    // 2,4,5,1,6

我们可以认为任务队列执行优先级: 同步 > 微任务 > 宏任务

async && await
  • async 是什么,做什么的?
  • await 从字面拆分来看,等待,它在等什么?

1、async

async function fn1() {
      return 123
}
function fn2() {
    return 123
}
console.log(fn1())  // Promise {<fulfilled>: 123} 
console.log(fn2())  // 123

直观来看,async 无非就是把return值用Promise.resolve()包装了一下。
注:

  • 语义上理解,async表示函数内部有异步操作
  • await要写在async函数内部,否则报错

2、await
await 在等什么?一句话概括:await等的是右侧【表达式】的结果
等到之后,对于await来说要做什么?分情况

  • 不是promise对象
  • 是promise对象
async function async1() {
    console.log( 'async1 start' )
    await async2()
    console.log( 'async1 end' ) // await async2()阻塞了它
}
async function async2() {
    console.log( 'async2' )
}
async1()
console.log( 'script start' )  // 同步
//  async1 start    async2    script start   async1 end

这里注意一点,可能大家都知道await会让出线程,阻塞后面的代码,那么上面例子中, ‘async2’ 和 ‘script start’ 谁先打印呢?
是从左向右执行,一旦碰到await直接跳出, 阻塞async2()的执行?
还是从右向左,先执行async2后,发现有await关键字,于是让出线程,阻塞代码呢?
实践的结论是: 从右向左的。先打印async2,后打印的script start

之前说的await等到,做什么分两种情况:

  • 如果等到表达式值非 promise ,表达式值将进入队列,await阻塞后面代码,先执行async外面的同步代码 ,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果
  • 如果它等到的是一个 promise 对象,表达式值不会进入队列,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。
async function async1() {
    console.log( 'async1 start' )
    await async2()
    console.log( 'async1 end' )
}
async function async2() {
    // console.log( 'async2' )
    return new Promise(resolve=>{
      resolve()
    }).then(value=>{
      console.log('微任务');
    })
}
async1()
console.log( 'script start' )
打印结果: async start1   script start   微任务   async1 end

上述代码改造,打印结果就会发生变化。细品

最后看一道以前「今日头条」类似面试题:

async function async1() {
      console.log('async1 start');
      await async2();
      console.log('async1 end');
    }

    async function async2() {
      console.log('async2');
    }

    console.log('script start');
    setTimeout(function () {
      console.log('setTimeout');
    }, 0)

    async1();

    new Promise(function (resolve) {
      console.log('promise1');
      resolve();
    }).then(function () {
      console.log('promise2');
    });

    console.log('script end');
    // script start  async1 start  async2  promise1  script end  async1 end  promise2  setTimeout
    

你过关了吗!!!每个人的理解说得都不一定准确,只能自己多思考了。

辅助功法传送门:👇
1、async/await讲解
2、阮老师promise讲解

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值