async-await与try-catch

async、await与try、catch

async

是Generator函数的语法糖,Generator函数是ES6提供的异步编程的解决方案

理解:表示函数里有异步操作,async函数可以理解多个异步操作包装成的promise对象

返回值:promise对象

      async function add(num1, num2) {
        const val = num1 + num2;
        return val;
      }
      add(1, 4)
        .then((val) => {
          console.log(val);
        })
        .catch((reason) => {
          console.log(reason);
        });

函数add的返回值会成为then中回调函数的参数,如果add函数内部有错误或主动抛出错误,返回的 promise会是rejected状态,会被catch接收到

await

作用:

1》一是作为求值关键字;.then的语法糖,可以拿到promise的结果

2》二是将异步操作变成同步操作;await后面的代码执行时机一定是在await后的promise执行后(执行时机有点像写在promise回调中的代码)

await 后面一般跟的是一个 promise 对象,如果不是,会转成一个 resolved 状态的 promise 对象

await语句后的promise变为rejected状态,reject的参数会被catch的回调接收到,而且整个 async 函数会被中断执行,即await后的代码就不会执行了(前提是没有catch捕获)

await必须放在async函数中,不然会报错

      async function add(num1, num2) {
        const re = await Promise.reject("err");
        console.log("await后的promise状态改变后");
        const val = num1 + num2;
        return val;
      }
      add(1, 4)
        .then((val) => {
          console.log(val);
        })
        .catch((reason) => {
          console.log(reason);  // 只有这个打印了 err
        });

async和await搭配使用

await必须放在async函数中,但是使用async时可以没有await

async中返回的promise的状态

async中返回的promise状态变化有三种原因:

1》执行出错或主动抛出错误:返回一个rejected状态的promise,错误或异常原因就是catch中回调函数的参数

2》遇到return:返回一个resolve状态的promise,return的值 就是then中resolved回调函数的参数

3》await后的promise执行完成,这个promise状态变为resolved,那么只要async中没有错误或主动抛出异常,返回的promise状态就是resolved,否则就是rejected

await后的promise状态变为rejected后,那么后面的代码将不再执行(相当抛出了错误,却没有捕获)

async中返回的promise对象回调函数的参数

1》如果await的promise状态变为resolved,而且async中没报错,没有主动抛出异常,那么async函数的返回值就是参数的值,如果没有 return ,则参数为undefined

2》如果async中由错误或await后的promise状态变为rejected(reject() 的作用就是和throw一样),错误原因就是catch的参数值

错误问题

如何捕获promise中的异步错误

1》try … catch 捕获错误

try catch不能捕获到异步错误,但是await可以将他转为同步,所以可以捕获到

如果由多个await,可以统一放在一个try…catch中

      async function add(num1, num2) {
        const re = await Promise.reject(10); 
        console.log(20);
        const val = num1 + num2;
        return val;
      }
      add(1, 4)
        .then((val) => {
          console.log(val);
        })
        .catch((reason) => {
          console.log(reason); // 10
        });

上面代码只打印出10,如果没有将await中的代码放入try… catch中,await后的promise状态变为rejected,相当于抛出一个错误 (相当于 throw 10 ),错误在里面没有捕获到,所以后面的代码不会执行,async函数返回一个rejected状态的promise,catch中的回调执行

      async function add(num1, num2) {
        try {
          const re = await Promise.reject(10);
          console.log(20);
        } catch (err) {
          console.log("err", err); // err 10
        }
        const val = num1 + num2;
        return val;
      }
      add(1, 4)
        .then((val) => {
          console.log(val); // 5
        })
        .catch((reason) => {
          console.log(reason);
        });

打印 err 10 和 5,try…catch捕获到await后面的Promise抛出的错误,打印err 10,由于抛出了错误,所以try中的20不会打印,try…catch后面的代码继续执行,async函数返回一个resolved状态的promise,所以打印出5

2》await后的promise跟catch

      async function add(num1, num2) {
        const re = await new Promise((resolve, reject) => {
          setTimeout(() => {
            reject(10);
          });
        }).catch((err) => {
          console.log(err);
        });
        console.log(20);
        const val = num1 + num2;
        return val;
      }
      add(1, 4)
        .then((val) => {
          console.log(val); // 5
        })
        .catch((reason) => {
          console.log(reason);
        });

打印结果 10 20 5;await后的promise对象变为rejected状态后,就会执行里面catch的回调,打印10,await后面的代码,只有当await后的promise改变之后,才会执行,打印20,async函数返回resolved状态的promise,打印5

补充:try catch错误捕获问题(不能捕获到异步错误)

1》setTimeout中的异步错误捕获不到:a没有定义,所以控制台报错,没有捕获到错误

      try {
        setTimeout(() => {
          console.log(a)
        }, 10)
      } catch (err) {
        console.log(err)
      }

try catch 与 promise:promise 内部 已经加了 try catch 处理了异常,所以不能冒泡到外面

2》在promise内部使用try catch

      new Promise((resolve, reject) => {
        try {
          reject(3) // 捕获不到,而且会先打印99,再报错:Uncaught (in promise) 3
          //   console.log(a) // 能捕获到
          //   throw new Error('这就是个错误') // 能捕获到
          console.log(99)
        } catch (err) {
          console.log(err)
        }
      })

3》在promise外部使用try catch;执行器函数中都是同步代码

      try {
        new Promise((resolve, reject) => {
          //   reject(6) // 捕获不到,先打印777,然后报错:Uncaught (in promise) 6
          console.log(a) //捕获不到;直接报错:referenceError: a is not defined,不会打印777
          //   throw 6 // 捕获不到;先打印777,后报错:Uncaught (in promise) 6 
        })
      } catch (err) {
        console.log(err)
      }
      console.log(777)

4》在promise外部使用try catch;实际上一般是这种,因为promise中一般都是处理异步任务

      try {
        new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log(a) //不会打印7,直接报错: Uncaught ReferenceError: a is not defined
            //  throw 6,//不会打印7,直接报错:Uncaught 6
            // reject(6) // 打印7,然后报错:Uncaught 6
            console.log(7)
          })
        })
      } catch (err) {
        console.log(err)
      }

promise中不使用try catch,也没有设置 .then .catch回调函数

      new Promise((resolve, reject) => {
        reject(3) // 打印88,然后报错:Uncaught (in promise) 3
        // console.log(a) // 不会打印88,报错:ReferenceError: a is not defined
        // throw 3 // 不会打印88,Uncaught (in promise) 3
        console.log(88)
      })

结论:promise中如果没有写catch,那么相当于默认加了一个在catch,并且catch中抛出错误throw(err);即使执行器函数是一个同步函数,在里面执行了一个同步任务,发生了语法错误,由于是在回调catch中抛出的错误,是一个异步微任务,所以即使在promise外面套了一层try catch也捕获不到

try catch 如果套在promise外层,没有使用async await是捕获不到错误的

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值