美文网首页
promise-catch-loader

promise-catch-loader

作者: 叶小七的真命天子 | 来源:发表于2020-08-13 16:43 被阅读0次

之前看了别人写的async-catch-loader,于是乎自己尝试写着玩,想对所有Promise对象加入catch函数,但是发现在AST中根本判断不了变量是否是promise(可能是自己太菜了尚且不知道如何在ast中判断~),于是只写了在显示Promise声明的情况下的场景。还有好多场景,没时间研究了(╥╯^╰╥)

直接上代码

const core = require('@babel/core')
const parser = require('@babel/parser')
const t = require('@babel/types')
const traverse = require('@babel/traverse').default

const DEFAULT_OPTIONS = {
  catchCode: identifier => `console.error(${identifier})`,
  identifier: 'e'
}

module.exports = function (source) {
  let options = {
    ...DEFAULT_OPTIONS,
    ...this.getOptions()
  }
  let ast = parser.parse(source, {
    sourceType: 'module' // 支持 es6 module
  })
  if (typeof options.catchCode === 'function') {
    options.catchCode = options.catchCode(options.identifier)
  }
  let catchNode = parser.parse(options.catchCode).program.body

  const promises = []

  traverse(ast, {
    NewExpression ({ node, parentPath }) {
      const isPromise = node.callee.name === 'Promise'
      if (isPromise) {
        promises.push(parentPath.node.id.name)
      }
    },
    CallExpression (path) {
      const { node, parentPath } = path
      const callee = node.callee
      // !t.isMemberExpression(parentPath.node)这一层判断是替换父节点之后,防止p.then()表达式再次进入
      if (!t.isMemberExpression(parentPath.node) && t.isMemberExpression(callee) && t.isIdentifier(callee.property) && t.isIdentifier(callee.object)) {
        const isThenIdentifier = callee.property.name === 'then'
        const isPromise = promises.includes(callee.object.name)
        if (isThenIdentifier && isPromise) { // 说明是一个promise调用then表达
          const params = t.arrowFunctionExpression([t.identifier(options.identifier)], t.blockStatement(catchNode))
          const expressionStatement = t.expressionStatement(
            t.callExpression(
              t.memberExpression(
                node,
                t.identifier('catch')
              ),
              [params]
            )
          )
          parentPath.replaceWith(expressionStatement)
        }
      }
    }
  })
  return core.transformFromAstSync(ast, null, {
    configFile: false
  }).code
}

const p = new Promise((resolve, reject) => {
  resolve()
})
p.then(()=>{})

上面代码将转成

const p = new Promise((resolve, reject) => {
  resolve();
});
p.then(()=>{}).catch(err => {
  console.error(err);
});

最后,说明下此为闲暇之余自己练手,再此记录下而已~

相关文章

  • promise-catch-loader

    之前看了别人写的async-catch-loader,于是乎自己尝试写着玩,想对所有Promise对象加入catc...

网友评论

      本文标题:promise-catch-loader

      本文链接:https://www.haomeiwen.com/subject/wlcidktx.html