• 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);
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    函数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
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    上面代码只打印出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);
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    打印 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);
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    打印结果 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)
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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)
            }
          })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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)
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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)
          })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

  • 相关阅读:
    Rust嵌入式编程---panic处理和异常处理
    【网站架构】同是响应式布局为什么我的页面布局是错乱的?布局工作占了大部分前端工作量怎样才能做好响应式布局?一份代码如何适配多个显示端?
    Vue权限控制
    她从家乡自贡起步,努力奋斗进京任职
    cs231n--正则化与优化
    webpack不同环境下使用CSS分离插件mini-css-extract-plugin
    ChinaSkills-高职组网络系统管理大赛-WinSer 2019 互联网网卡检测服务笔记
    dreamweaver网页设计作业制作 学生个人网页猫眼电影 WEB静态网页作业模板 大学生个人主页博客网页代码 dw个人网页作业成品
    智慧农业数字孪生应用案例,数字化农业建设发展现状
    数据结构——树(树的概念、优缺点、二叉树)
  • 原文地址:https://blog.csdn.net/weixin_50576800/article/details/126918945