async如果不加 try/catch 会发生什么事?

简介: 在开发过程中,为了保证系统健壮性,或者是为了捕获异步的错误,需要频繁的在 async 函数中添加 try/catch,避免出现上述示例的情况

// 示例
async function fn() {
let value = await new Promise((resolve, reject) => {

reject('failure');

});
console.log('do something...');
}
fn()
复制代码
导致浏览器报错:一个未捕获的错误

在开发过程中,为了保证系统健壮性,或者是为了捕获异步的错误,需要频繁的在 async 函数中添加 try/catch,避免出现上述示例的情况
可是我很懒,不想一个个加,懒惰使我们进步😂
下面,通过手写一个babel 插件,来给所有的async函数添加try/catch
babel插件的最终效果
原始代码:
async function fn() {
await new Promise((resolve, reject) => reject('报错'));
await new Promise((resolve) => resolve(1));
console.log('do something...');
}
fn();
复制代码
使用插件转化后的代码:
async function fn() {
try {

await new Promise((resolve, reject) => reject('报错'));
await new Promise(resolve => resolve(1));
console.log('do something...');

} catch (e) {

console.log("\nfilePath: E:\\myapp\\src\\main.js\nfuncName: fn\nError:", e);

}
}
fn();
复制代码
打印的报错信息:

通过详细的报错信息,帮助我们快速找到目标文件和具体的报错方法,方便去定位问题
babel插件的实现思路
1)借助AST抽象语法树,遍历查找代码中的await关键字
2)找到await节点后,从父路径中查找声明的async函数,获取该函数的body(函数中包含的代码)
3)创建try/catch语句,将原来async的body放入其中
4)最后将async的body替换成创建的try/catch语句
babel的核心:AST
先聊聊 AST 这个帅小伙🤠,不然后面的开发流程走不下去
AST是代码的树形结构,生成 AST 分为两个阶段:词法分析和 语法分析
词法分析
词法分析阶段把字符串形式的代码转换为令牌(tokens) ,可以把tokens看作是一个扁平的语法片段数组,描述了代码片段在整个代码中的位置和记录当前值的一些信息
比如let a = 1,对应的AST是这样的

语法分析
语法分析阶段会把token转换成 AST 的形式,这个阶段会使用token中的信息把它们转换成一个 AST 的表述结构,使用type属性记录当前的类型
例如 let 代表着一个变量声明的关键字,所以它的 type 为 VariableDeclaration,而 a = 1 会作为 let 的声明描述,它的 type 为 VariableDeclarator
AST在线查看工具:AST explorer
再举个🌰,加深对AST的理解
function demo(n) {
return n * n;
}
复制代码
转化成AST的结构
{
"type": "Program", // 整段代码的主体
"body": [

{
  "type": "FunctionDeclaration", // function 的类型叫函数声明;
  "id": { // id 为函数声明的 id
    "type": "Identifier", // 标识符 类型
    "name": "demo" // 标识符 具有名字 
  },
  "expression": false,
  "generator": false,
  "async": false, // 代表是否 是 async function
  "params": [ // 同级 函数的参数 
    {
      "type": "Identifier",// 参数类型也是 Identifier
      "name": "n"
    }
  ],
  "body": { // 函数体内容 整个格式呈现一种树的格式
    "type": "BlockStatement", // 整个函数体内容 为一个块状代码块类型
    "body": [
      {
        "type": "ReturnStatement", // return 类型
        "argument": {
          "type": "BinaryExpression",// BinaryExpression 二进制表达式类型
          "start": 30,
          "end": 35,
          "left": { // 分左 右 中 结构
            "type": "Identifier", 
            "name": "n"
          },
          "operator": "*", // 属于操作符
          "right": {
            "type": "Identifier",
            "name": "n"
          }
        }
      }
    ]
  }
}

],
"sourceType": "module"
}

相关文章
|
2月前
|
前端开发 UED
【面试题】async/await 函数到底要不要加 try catch ?
【面试题】async/await 函数到底要不要加 try catch ?
|
8月前
|
Java
try()catch{}写法
try()catch{}写法
31 0
|
2月前
|
前端开发 UED
【面试题】 async/await 函数到底要不要加 try catch ?
【面试题】 async/await 函数到底要不要加 try catch ?
【面试题】 async/await 函数到底要不要加 try catch ?
|
12月前
|
JavaScript 前端开发 Go
async vs defer 的区别
async vs defer 的区别
52 0
如何给所有的 await async 函数添加try/catch?
如何给所有的 await async 函数添加try/catch?
|
8月前
try和catch的用法
try和catch的用法
54 1
|
2月前
|
存储 缓存 IDE
细琢磨,try catch finally 执行顺序与返回值
细琢磨,try catch finally 执行顺序与返回值
45 0
|
前端开发 UED
async/await 函数到底要不要加 try catch ?
async/await 函数到底要不要加 try catch ?
87 0
try...catch中,catch加了return,后面的代码是不会执行的
try...catch中,catch加了return,后面的代码是不会执行的
73 0