promise-catch-loader

之前看了別人寫的async-catch-loader,于是乎自己嘗試寫著玩,想對所有Promise對象加入catch函數(shù),但是發(fā)現(xiàn)在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)這一層判斷是替換父節(jié)點(diǎn)之后,防止p.then()表達(dá)式再次進(jìn)入
      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調(diào)用then表達(dá)
          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(()=>{})

上面代碼將轉(zhuǎn)成

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

最后,說明下此為閑暇之余自己練手,再此記錄下而已~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容