Promise,async和await的面试题

Promise,async和await的面试题

async和await的基本原理

async

asyncGenerator函数的语法糖,使用async表示,在函数内部使用await表示异步,相对于Generatorasync做了一些改进:

  • Generator的执行需要依靠执行器,async内置执行器,自动执行
  • async代替了*await代替了yield,语义化更好
  • async函数返回值是一Promise对象

await

await意思是async wait(异步等待)。这个关键字只能在使用async定义的函数里面使用。await会解析Promise对象的值,async会等所有的await命令的Promise对象执行完,才会发生状态的改变。

一、关于Promise的执行顺序

创建Promise是同步的,当执行完resolve();后,状态变为resolved,后面的.then立即放入微队列,第二个.then放入第一个.then返回promise对象的缓存队列中(并不是微队列)。

1.

new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
  .then(() => {
    console.log("外部第一个then");
    return new Promise((resolve, reject) => {
      console.log("内部promise");
      resolve();
    })
    .then(() => {
    console.log("内部第一个then");
    })
    .then(() => {
    console.log("内部第二个then");
    });
  })  这里返回的对象是最后一个.then返回的对象,第一次时状态为‘pending’
  .then(() => { 所以第一次这里会缓存起来并不是加入队列
    console.log("外部第二个then");
  });
 

2.

new Promise((resolve, reject) => {
  console.log("外部promise");
  resolve();
})
  .then(() => {
    console.log("外部第一个then");
    new Promise((resolve, reject) => {
      console.log("内部promise");
      resolve();
    })
      .then(() => {
        console.log("内部第一个then");
      })
      .then(() => {
        console.log("内部第二个then");
      });
  }) 这里返回的是undefined 的promise对象
  .then(() => { 第一次时这个promise对象已经是resolved了,所以立即加入队列
    console.log("外部第二个then");
  });

3.

console.log(1);
setTimeout(() => {
    console.log(2);
});
new Promise(resolve => {
    console.log(3);
    resolve('resolve');
    console.log(4);
    reject('error')
}).catch((err) => {
    console.log(err);
}).then((res) => {
    console.log(res)
});
Promise.resolve().then(() => {
    console.log(5);
});
console.log(6);

执行catch时,状态已经变为resolved,就不会执行catch的回调函数,而执行默认的成功的回调函数:onResolved : value => value。一定要注意这里直接把catch的回调函数替换了,所以不会再执行console.log(err);了。

1
3
4
6
5
resolve
2

4.
console.log('start');
setTimeout(() => {
    console.log('time');
});

const p1 = new Promise((resolve, reject) => {
    console.log('resolve1');
}).then(() => {
    console.log('resolve');
});
console.log('end');

start
resolve1
end
time

由于没有调用resolve,所以该promise函数一直处于pending状态,并不会执行.then函数。

二、关于async和await

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回(交出线程,跳出 async 函数体),等到触发的异步操作完成,再接着执行函数体内后面的语句。

await后面的语句会立即执行,返回promise时,由于考虑到异步操作,且下一行语句需要知道结果才能执行,所以返回的promise会等后面的同步语句执行完之后放入微队列中。

1.

async function async1(){
   console.log('async1 start');
   await async2();  会先执行async2函数,然后跳出async1,执行同步语句,然后将返回的promise放入微队列
   // 会立即放入微队列,相当于.then,所以会在promise2的前面
   console.log('async1 end');
}
async function async2(){
   console.log('async');
}
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
async
promise1
script end
async1 end
promise2
setTimeout

2.

async function async1() {
    console.log('async1 start');
    const result = await async2();
    console.log(result);
    // 会先执行async2函数, 然后跳出async1, 同时将返回的promise放入微队列
    console.log('async1 end');
}
async function async2() {
    console.log('async');
    return "testAwait";
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0);
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
new Promise(function(resolve) {
    console.log('promise3');
    resolve();
}).then(function() {
    console.log('promise4');
});
console.log('script end');

script start
async1 start
async
promise1
promise3
script end
promise2
promise4
testAwait
async1 end
setTimeout

三、Promise.resolve()会造成三次微队列入队延迟

先来看一段代码,下面这段代码输出 0,1,2,3,4,5,6

Promise.resolve().then(() => {
    console.log(0);
    return Promise.resolve(4);
}).then((res) => {
    console.log(res);
});
Promise.resolve().then(() => {
    console.log(1);
}).then(() => {
    console.log(2);
}).then(() => {
    console.log(3);
}).then(() => {
    console.log(5);
}).then(() => {
    console.log(6);
});

参考博文:
[1]: https://juejin.cn/post/6844903621360943118

  • 4
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
异步编程是现代软件开发中非常重要的一部分,而在JavaScript中,async和await是用来处理异步操作的两个关键字。下面是一些关于async和await面试题: 1. async和await是什么?它们的作用是什么? - async是用来声明一个函数是异步的,它会返回一个Promise对象。 - await用于等待一个Promise对象的解析结果,并且只能在async函数内部使用。它可以暂停函数的执行,直到Promise对象的状态变为resolved(已解决)。 2. async函数返回什么? - async函数始终返回一个Promise对象。这个Promise对象的结果取决于函数中的return语句。 3. 在什么情况下使用async和await? - 当需要处理异步操作时,可以使用async和await来编写更清晰、更易读的异步代码。 - 通常情况下,我们会将回调函数、Promise链式调用或者Generator函数转换为使用async和await的代码。 4. async函数中可以有多个await吗? - 是的,async函数中可以有多个await语句。每个await语句会暂停函数的执行,直到对应的Promise对象解析为已解决状态。可以按需使用多个await语句来处理多个异步操作。 5. async函数中如何处理错误? - 可以使用try-catch语句块来捕获和处理错误。在使用await等待一个Promise对象时,如果该Promise对象的状态变为rejected(已拒绝),则会抛出一个异常,可以通过try-catch来捕获并处理该异常。 这些面试题可以帮助你了解async和await的基本概念和用法。当然,还有更多的问题可以进一步探讨和学习。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值