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"
}作者:海阔_天空链接:https://juejin.cn/post/715543...来源:稀土掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(async如果不加 try/catch 会发生什么事?)