async/await 全解析

前言

async 函数是使用async关键字声明的函数。 async 函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。

一. async

async 函数返回的是一个 Promise 对象。async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象。如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象

async function aa() {
  return  111
}

aa()
相当于

Promise.resolve(111)
  1. 函数加上async函数前缀之后,函数作用域中的部分相当于
new Promise((resolve,reject) => resolve(1233) )
//或者
new Promise((resolve,reject) => reject('出错了') )

所以此时函数作用域内部代码是同步执行的

二. await

await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值,
所以,await 后面实际是可以接普通函数调用或者直接量的,所以下面这个示例完全可以正确运行

function getSomething() {
    return "something";
}

async function testAsync() {
    return Promise.resolve("hello async");
}

async function test() {
    const v1 = await getSomething();
    const v2 = await testAsync();
    console.log(v1, v2);
}

test();
  1. 如果await后面 不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西;
  2. 如果await后面是一个 Promise 对象,await 就会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果,这也是await放在函数作用域里面的原因,即便有阻塞,也是阻塞了函数作用域范围的代码,而不会影响函数外的作用域;
  3. 如果await后面的函数本身就是返回一个promise,则该函数可不加async前缀。

三. 错误捕获

 async function aa() {
   let s1 = new Set();
   let p1,p2,p3;
 	p1 = await Promise.resolve(1);
 	p2 = await Promise.reject(2);
 	p3 = await Promise.resolve(3)
   s1.add(p1);
   s1.add(p2);
   s1.add(p3);
   return s1
 }
aa().then(res => {
console.log(res)
})

报错信息
在这里插入图片描述
因为p2状态为rejected,会阻塞函数作用域内p2之后的代码执行

捕获错误的方式

1. Promise
aa().then(res => {
 console.log(res)
 },(err) => {
    console.log(err)  // 2
 })
2. try catch
async function aa() {
    let s1 = new Set();
    let p1,p2,p3;
    try {
        p1 = await Promise.resolve(1);
      p2 = await Promise.reject(2);
      p3 = await Promise.resolve(3)
    } catch(err) {
        console.log(err,'err1')
    }
    s1.add(p1);
    s1.add(p2);
    s1.add(p3);
    return s1
  }
 aa().then(res => {
 console.log(res)
 },(err) => {
    console.log(err)
 })

(1) . try catch和Promise错误捕获都存在时,会优先try catch;
(2) . 因为将await相关的代码包裹在try catch中,所以上述代码并不会阻塞try catch之后的代码执行;
(3). 上述try catch的错误捕获,只能捕获到第一个rejected状态的promise实例错误信息,因为阻塞缘故,且只能捕获一个。

3. 如何不受错误阻塞影响,返回成功的promise实例,且抛出rejected状态的promise实例错误信息?

实现代码如下:

async function aa() {
    let s1 = new Set();
    let p1,p2,p3;
    try {
        p1 = await Promise.resolve(1);
    } catch(err) {
        console.log(err,'err1')
    }
    try {
        p2 = await Promise.reject(2);
    } catch(err) {
        console.log(err,'err2')
    }
    try {
        p3 = await Promise.resolve(3);
    } catch(err) {
        console.log(err,'err3')
    }
    s1.add(p1);
    s1.add(p2);
    s1.add(p3);
    return s1
  }

四. await阻塞情况

function handleAdd() {
  return new Promise((resolve, reject) => {
    console.log('hello');
  });
}

async function test() {
  try {
    await handleAdd();
  } catch (err) {
    console.log(err, 'err12343');
  } finally {
    console.log('final');
  }

  console.log(1233, 'testValue');
}
test();

虽然利用try catch可以在一定程度上防止进程阻塞,但是前提是以promise状态已更改为fulfilled或rejected,假如是pending状态,还是会阻塞后面代码执行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值