You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript装饰器实现函数耗时返回及批量统计方案咨询

TypeScript 函数耗时统计实现方案

1. 装饰器返回原返回值+耗时的实现

你当前的代码存在两个可优化点:

  • 你定义的是带参数的装饰器工厂,直接写@createTimestamps会报错,需要传入message参数使用
  • 原有逻辑没有接收原函数返回值,也没有对外返回耗时数据

如果要同时拿到原函数返回值和耗时,最直接的方式是把结果包装为包含result(原返回值)和duration(耗时毫秒数)的对象,改造后的代码如下:

// 定义返回值的泛型类型,方便TS类型推导
type TimedResult<T> = {
  result: T;
  duration: number;
}

export function createTimestamps(message: string) {
  return function (target: any, name: string, descriptor: PropertyDescriptor) {
    const method = descriptor.value;
    // 支持透传原函数的参数
    descriptor.value = async function (...args: any[]): Promise<TimedResult<any>> {
      const startTime = Date.now();
      console.log(`${message} started at: ${new Date(startTime).toLocaleString("en-GB")}`);
      // 接收原函数返回值
      const result = await method.apply(this, args);
      const endTime = Date.now();
      const duration = endTime - startTime;
      console.log(`${message} completed at: ${new Date(endTime).toLocaleString("en-GB")}`);
      console.log(`${message} took ${duration}ms to complete.`);
      // 返回包装后的结果
      return { result, duration };
    };
  };
}

使用方式:

class Demo {
  // 传入message参数
  @createTimestamps("测试函数")
  async newfunc(): Promise<string> {
    return "typescript";
  }
}

// 调用时即可同时拿到返回值和耗时
const demo = new Demo();
const { result, duration } = await demo.newfunc();
console.log(result); // 输出 typescript
console.log(duration); // 输出执行耗时

如果你不想破坏原函数的返回结构,也可以选择把耗时挂载到全局的统计对象、或者函数的自定义属性上,但包装返回对象的方式兼容性最好,类型推导也更友好。

2. 批量函数自动统计耗时的实现

如果不想逐个给函数加装饰器,可以根据你的函数类型选择对应方案:

  • 如果是类的方法:可以写一个类装饰器,自动遍历类的所有原型方法,给符合条件的异步方法批量加耗时统计逻辑,不需要手动加@装饰器
  • 如果是独立的普通函数:可以写一个高阶包装函数,批量处理你需要统计的函数数组,批量返回包装后的带耗时统计的函数

示例:批量包装类方法的类装饰器

function batchTimeStatistics(messagePrefix: string) {
  return function (target: any) {
    // 遍历类原型的所有方法
    const methods = Object.getOwnPropertyNames(target.prototype);
    methods.forEach(methodName => {
      const descriptor = Object.getOwnPropertyDescriptor(target.prototype, methodName);
      // 过滤掉构造函数、非函数属性
      if (methodName === 'constructor' || typeof descriptor?.value !== 'function') return;
      // 自动给方法加耗时装饰器
      const timedDescriptor = createTimestamps(`${messagePrefix}-${methodName}`)(target, methodName, descriptor);
      Object.defineProperty(target.prototype, methodName, timedDescriptor);
    })
  }
}

// 使用时只需要给类加一个装饰器,所有类方法都会自动加上耗时统计
@batchTimeStatistics("用户模块")
class UserService {
  async getUserInfo() { return {} }
  async updateUser() { return true }
}

3. 常用第三方库推荐

  • time-span:轻量耗时统计工具,支持高精度(纳秒级)统计,无额外依赖,有完善的TS类型支持
  • stopwatch-node:功能更丰富的计时工具,支持分段计时、暂停重启等能力,适合复杂耗时统计场景

注意事项

  • 需要在tsconfig.json中开启experimentalDecorators: true才能使用装饰器语法
  • 上述代码仅支持异步函数,如果需要兼容同步函数,可在装饰器中判断方法返回值是否为Promise,分别处理同步/异步逻辑,避免同步函数被强制转为异步返回

内容的提问来源于stack exchange,提问作者simeon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 08:48:02