• Promise,async,await 面试题


    推荐先看Promise 相关知识点

    5,面试题

    1

    结果 1,5,2,3,4

    const promise = new Promise((resolve, reject) => {
      console.log(1);
      setTimeout(() => {
        console.log(2);
        resolve();
        console.log(3);
      });
    });
    
    promise.then(() => {
      console.log(4);
    });
    
    console.log(5);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    因为 then() 中的回调函数虽然是微任务,但也得等到 promise 变为 fulfilled 状态才会执行。

    2

    结果 1,3,2

    async function fun() {
      console.log(1); // 同步
      const n = await 2;
      console.log(n);
    }
    
    fun();
    console.log(3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    因为 fun() 函数中的同步语句会直接执行,异步的才会延迟执行。

    // 相当于
    function fun() {
      console.log(1);
      Promise.resolve(2).then((n) => {
        console.log(n);
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3

    结果 1,4,2,3

    async function fun() {
      console.log(1); // 同步
      const n = await 2;
      console.log(n);
    }
    
    (async () => {
      await fun();
      console.log(3);
    })();
    
    console.log(4);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    同理,立即执行函数执行后,await fun() 中的同步代码先执行,异步代码进入微队列等待执行。所以先输出 1 后输出 4。

    4

    结果 Promise {},Promise {},4,1,3,1

    async function fun1() {
      return 1;
    }
    
    async function fun2() {
      const n = await fun1();
      console.log(n); // 1
      return 2; // 没用被用到
    }
    
    async function fun3() {
      const n = fun2(); // 注意没有 await
      console.log(n);
      return 3;
    }
    
    fun3().then((n) => {
      console.log(n); // n 是 fun3 的返回值 3
    });
    
    fun3();
    
    console.log(4);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    1,先看同步代码的执行。

    • 第1个 fun3() 执行,会执行 fun2(),再执行 await fun1(),会将 async fun1 返回的 Promise 对象的后续处理,放到微队列中等待执行(任务1)。
    const n = await fun1();
    console.log(n);
    
    // 相当于
    new Promise((resolve) => {
      resolve(1)
    }).then((n) => {
      console.log(n);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 因为 fun2async 修饰,而且还有异步代码,所以此时 fun2() 执行的结果是一个 pending 状态的 Promise 对象,所以输出 Promise {}fun3() 的后续处理:then() 的回调函数进入微队列等待执行(任务2)。
    • 第2个 fun3() 执行,再次输出 Promise {},并添加微任务3
    • 输出 4

    2,接下来看异步代码的执行。

    • 执行微队列中的任务1输出 1,任务2输出 3,任务3输出 1

    5

    结果 1

    Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)
    
    • 1

    参考 3.2 的知识点。then() 的参数不是函数,说明没有对前一个任务做后续处理,相当于无效代码。

    // 等价
    Promise.resolve(1).then(console.log)
    
    • 1
    • 2

    6

    结果:promise1,undefined,end,promise2,promise3,promise4,Promise {},after1

    var a
    var b = new Promise((resolve, reject) => {
      console.log('promise1')
      setTimeout(() => {
        resolve()
      }, 1000)
    })
      .then(() => {
        console.log('promise2')
      })
      .then(() => {
        console.log('promise3')
      })
      .then(() => {
        console.log('promise4')
      })
    
    a = new Promise(async (resolve, reject) => {
      console.log(a)
      await b
      console.log(a)
      console.log('after1')
      await a
      resolve(true)
      console.log('after2')
    })
    console.log('end')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    注意,ba 都是右边 Promise 执行的结果。右边先执行,再赋值给左边的变量。

    1,先看同步代码执行

    • 执行 b 右边的表达式,输出 promise1setTimeout 的回调函数进入宏队列等待执行。此时 b 被赋值为一个 pending 状态的 Promise 对象。
    • 执行 a 右边的表达式,输出 undefined(此时 a 未赋值)。
    • 执行 await b,因为此时 bpending 状态,所以后续代码都不会执行,所以 a 也被赋值为一个 pending 状态的 Promise 对象
    • 输出 end

    2,再看异步代码执行

    • 没有微队列,所以执行宏队列中 setTimeout 的回调函数,将 b 变为 fulfilled 状态,接着执行后续 3个 then(),依次输出 promise2promise3promise4
    • 现在 b 变为 fulfilled 状态,所以 await b 执行完成,开始执行后续代码。
    • 注意到 a 现在还是一个 pending 状态的 Promise 对象,所以输出 Promise {} ,再输出 after1
    • 执行 await a,将永远等待,因为没有更改状态的机会。

    7

    结果 script start,async1 start,async2,p1,script end,async1 end,p2,settimeout

    async function async1() {
      console.log('async1 start')
      await async2()
      console.log('async1 end')
    }
    
    async function async2() {
      console.log('async2')
    }
    
    console.log('script start')
    
    setTimeout(() => {
      console.log('settimeout')
    }, 0)
    
    async1()
    
    new Promise(function (resolve) {
      console.log('p1')
      resolve()
    }).then(function () {
      console.log('p2')
    })
    
    console.log('script end')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    1,先看同步代码执行

    • 输出 script startsetTimeout 的回调函数进入宏队列等待执行。
    • 执行 async1(),输出 async1 start
    • 执行 await async2() 中的同步代码,输出 async2await async2() 之后的代码,相当于在 then() 的回调函数中执行,所以进入微队列等待。
    await async2()
    console.log('async1 end')
    
    async function async2() {
      console.log('async2')
    }
    
    // 相当于
    new Promise((resolve) => {
      console.log('async2')
      resolve()
    }).then(() => {
      console.log('async1 end')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 输出 p1then() 的回调函数进入微队列等待。
    • 输出 script end

    2,再看异步代码执行。

    • 先执行微队列中的任务,输出 async1 end,再输出 p2
    • 再执行宏队列中的任务,输出 settimeout

    以上。

  • 相关阅读:
    Linux内核——IEEE 802.15.4开发者指南
    git LFS
    Redis使用lua脚本实现库存扣减
    图像处理那些算法
    MySQL介绍
    C++ 与基本数据类型:整型、布尔型与字符型
    python实现列表元素进行正交
    Build a Large Language Model (From Scratch) 从头开始构建大型语言模型(第二章)学习笔记(上)
    微服务:Sentinel篇
    SpringMVC基础篇:引言
  • 原文地址:https://blog.csdn.net/qq_40147756/article/details/132763936