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
相关产品推荐
相关产品推荐

