如何给async await批量添加try…catch?
- async和await是什么?
- 如何给async await批量添加try…catch
- babel插件的实现思路
- 插件的基本格式示例
- 寻找await节点
- 向上查找 async 函数
- 添加用户选项
- babel插件的安装使用
- 其他参考资料
async和await是什么?
在前端开发的工作过程中,async和await想必大家都很熟悉,只要发请求或者是基于promise的异步操作,都可以用promise的终极解决方案来操作,这样写可以使代码变得简介,并且在看代码的时候可以按照同步的代码去书写,(仅仅看上去是同步的,本质还是异步的
)
try…catch是什么东西?那么为什么要用try…catch呢?它的存在是为了解决什么问题的?
带着上边的三个问题我们来一一解答,try…catch是什么呢?举个例子,在生活中我们难免会犯错,当我们知道有些错误不可避免或者可能会出错的时候,我们会先去想好如果犯了错,应该怎么解决这个错误,那么try…catch也是如此,它是为了解决我们在书写代码的过程中可能会出错的地方,用try…catch包裹起来,如果这段代码成功的话,它是不会去执行catch里的代码的,相反,如果失败,它是不会去执行try里的代码的,当然我们有时候会不管这段代码成功或者失败,都要执行一些相应的操作,那么,就可以将代码写到finally里面,这样的话,无论这段代码成功或者失败,都会去执行这段代码,类似于promise当中的.then、.catch和.finally
,而我们利用async和await去发送请求时就可以利用try和catch去包裹一下,以防出错时候用户不知道是什么问题
如何给async await批量添加try…catch
如果我们每次写一个请求,手动给请求添加一个try…catch,这样肯定是可以的,总所周知,程序员都是比较懒的,能少写一个单词绝不多写一个字母,那么如何给async和await批量添加try…catch呢?
带着这个问题,我打开了百度,打算面向百度编程,最后是在掘金上边找到了一个利用babel来解决的方案,在此做一个记录,希望可以帮到更多的人~~~~
babel插件的实现思路
1)借助AST抽象语法树,遍历查找代码中的await关键字
2)找到await节点后,从父路径中查找声明的async函数,获取该函数的body(函数中包含的代码)
3)创建try/catch语句,将原来async的body放入其中
4)最后将async的body替换成创建的try/catch语句
插件的基本格式示例
module.exports = function (babel) {
let t = babel.type
return {
visitor: {
// 设置需要范围的节点类型
CallExression: (path, state) => {
do soming ……
}
}
}
}
1)通过 babel
拿到 types
对象,操作 AST 节点,比如创建、校验、转变等
2)visitor
:定义了一个访问者,可以设置需要访问的节点类型,当访问到目标节点后,做相应的处理来实现插件的功能
寻找await节点
回到业务需求,现在需要找到await节点,可以通过AwaitExpression
表达式获取
module.exports = function (babel) {
let t = babel.type
return {
visitor: {
// 设置AwaitExpression
AwaitExpression(path) {
// 获取当前的await节点
let node = path.node;
}
}
}
}
向上查找 async 函数
通过findParent
方法,在父节点中搜寻 async 节点
// async节点的属性为true
const asyncPath = path.findParent(p => p.node.async)
这里要注意,async 函数分为4种情况:函数声明 、箭头函数 、函数表达式 、函数为对象的方法
// 1:函数声明
async function fn() {
await f()
}
// 2:函数表达式
const fn = async function () {
await f()
};
// 3:箭头函数
const fn = async () => {
await f()
};
// 4:async函数定义在对象中
const obj = {
async fn() {
await f()
}
}
需要对这几种情况进行分别判断
module.exports = function (babel) {
let t = babel.type
return {
visitor: {
// 设置AwaitExpression
AwaitExpression(path) {
// 获取当前的await节点
let node = path.node;
// 查找async函数的节点
const asyncPath = path.findParent((p) => p.node.async && (p.isFunctionDeclaration() || p.isArrowFunctionExpression() || p.isFunctionExpression() || p.isObjectMethod()));
}
}
}
}
添加用户选项
用户引入插件时,可以设置exclude
、include
、 customLog
选项
exclude
: 设置需要排除的文件,不对该文件进行处理
include
: 设置需要处理的文件,只对该文件进行处理
customLog
: 用户自定义的打印信息
babel插件的安装使用
npm网站搜索babel-plugin-await-add-trycatch
有兴趣的朋友可以下载玩一玩
babel插件的安装使用
最终的代码可以参考这位大佬的github仓库
其他参考资料
Babel 插件手册
嘿,不要给 async 函数写那么多 try/catch 了
原文地址:
阿里面试官:如何给所有的async函数添加try/catch?