今日份快乐学习setTimeout,async,事件队列

712 阅读2分钟

由一道题引发的xue案,今天朋友发了道题,问先打印A 还是先打印B

async function A(){
await setTimeout(()=>{
console.log('AAAA')
return
},2000);
}
async function B(){
await  setTimeout(()=>{
console.log('BBBB')
},1000);
}
async function C(){
await A()
await B()
}
C()

来先上答案

image.png

开始乍一看这个不async吗?这不await吗?先打印A再打印B.

async 作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 异步函数的调用跟普通函数一样

await即等待,用于等待一个Promise对象。 它只能在异步函数 async function中使用,否则会报错它的返回值不是Promise对象而是Promise对象处理之后的结果await表达式会暂停当前 async function的执行,等待Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function,若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。如果 await 操作符后的表达式的值不是一个 Promise,那么该值将被转换为一个已正常处理的 Promise。

但仔细一看并不是这样,await是加在setTimeout前面并不在内部,setTimeout是同步,所以不受影响,setTimeout会被加到定时器线程,当定时结束,执行函数。按照setTimeout设置的时间短的先执行。


由此你以为就完了吗?礼尚往来,我给他还了一题。如下。

  async function a() {
    return setTimeout(() => { console.log('aaaaa') }, 2000);
  }
  async function b() {
    return setTimeout(() => { console.log('bbbbb') }, 1000);
  }
  function c() {
    console.log(setTimeout(() => { console.log('ccccc') }, 2000));
    console.log(setTimeout(() => { console.log('ddddd') }, 2000));
    a().then(res => (console.log(res)))
    console.log("@");
    b().then(res => (console.log(res)))
  }
  c()

先上答案

image.png

先说为什么会有数字1、2、3、4 注意在这里我把await改成了return,return一个setTimeout是会有返回值的,而这些数字就返回值是setTimeout的返回值,同时也是被执行的循序。setTimeout在函数C种被按顺序执行。

接下来我们来说一下这个@。为什么@在函数C中第四行却被先执行到3前面去了呢?因为a().then() b().then()是一个promise,而promise会被先加到微任务队列,而@在主线程中就先被执行了。

接下来setTimeout就是先按照设置时间短的先执行,时间一样的按照顺序执行,就得到如图结果