装饰器 如何 装饰异步方法

网上一波Decorator 的介绍,给类的方法增加装饰器的都是

let log = (type) => {

  return (target, name, descriptor) => {
    const method = descriptor.value;
    descriptor.value =  (...args) => {
      console.info(`(${type}) 正在执行: ${name}(${args}) = ?`);
      let ret;
      try {
        ret = method.apply(target, args);
        console.info(`(${type}) 成功 : ${name}(${args}) => ${ret}`);
      } catch (error) {
        console.error(`(${type}) 失败: ${name}(${args}) => ${error}`);
      }
      return ret;
    }
  }
}

class Super{

 @log('some_log')
 fetchData(){
 ...
 }

}

这么个操作。

但是如果被装饰fn 是一个promise、异步方法的话,如何做到

// 想在这里来一波log,上面的方法是可以做到的
fetch('http://xxx.xxx.com')
.then((res)=>{
// 想在这里来一波log ,怎么搞?
})

目前我的操作是 fn.toString() 插入一些代码, eval() 成一个方法。
有一些优雅的方法来做这件事么?

阅读 4.5k
2 个回答

建议用 中间件
promise return 后处理顺序在原代码执行顺序后面,类似这种

function asyncDecorator(name: string) {
  return function(target: Object, _: string, descriptor: PropertyDescriptor) {
    const raw = descriptor.value;

 
    descriptor.value = function(...args: any) {
      return raw.apply(this, args).then(() => {
        console.log('exec log: ', name);
      });
    };
  };
}

class Person {
  @asyncDecorator('test')
  fetch() {
    return new Promise((resolve, reject) => {
      setTimeout(resolve, 300);
    }).then(() => {
      console.log('fetch');
    });
  }
}

const person = new Person();

person.fetch();

可以参考 axios

本质都是js,举一反三一下就行了啊

let log = (type) => {

  return (target, name, descriptor) => {
    const method = descriptor.value;
    descriptor.value =  (...args) => {
      console.info(`(${type}) 正在执行: ${name}(${args}) = ?`);
      let ret;
      try {
        ret = method.apply(target, args);
        ret.then(result=>console.info(`(${type}) 成功 : ${name}(${args}) => ${result}`))
            .catch(error=>console.error(`(${type}) 失败: ${name}(${args}) => ${error}`))
      } catch (error) {
        console.error(`(${type}) 失败: ${name}(${args}) => ${error}`);
      }
      return ret;
    }
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题