MST

星途 面试题库

面试题:TypeScript 装饰器在复杂日志场景中的应用

假设你需要在一个大型项目中使用装饰器实现日志记录,该项目有多种类型的函数(异步、同步、类方法等),并且日志需要包含调用时间、参数信息以及执行结果。请编写一个通用的 TypeScript 装饰器来满足这些需求,并说明如何处理不同类型函数的差异。
35.3万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
import { format } from 'date-fns';

function logDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;

    if (typeof originalMethod === 'function') {
        if (originalMethod.constructor.name === 'AsyncFunction') {
            descriptor.value = async function (...args: any[]) {
                const startTime = new Date();
                const startFormatted = format(startTime, 'yyyy-MM-dd HH:mm:ss');
                console.log(`调用时间: ${startFormatted}, 参数信息: ${JSON.stringify(args)}`);
                try {
                    const result = await originalMethod.apply(this, args);
                    console.log(`执行结果: ${JSON.stringify(result)}`);
                    return result;
                } catch (error) {
                    console.log(`执行出错: ${JSON.stringify(error)}`);
                    throw error;
                }
            };
        } else {
            descriptor.value = function (...args: any[]) {
                const startTime = new Date();
                const startFormatted = format(startTime, 'yyyy-MM-dd HH:mm:ss');
                console.log(`调用时间: ${startFormatted}, 参数信息: ${JSON.stringify(args)}`);
                try {
                    const result = originalMethod.apply(this, args);
                    console.log(`执行结果: ${JSON.stringify(result)}`);
                    return result;
                } catch (error) {
                    console.log(`执行出错: ${JSON.stringify(error)}`);
                    throw error;
                }
            };
        }
    }

    return descriptor;
}

// 同步函数示例
class SyncClass {
    @logDecorator
    syncMethod(a: number, b: number) {
        return a + b;
    }
}

// 异步函数示例
class AsyncClass {
    @logDecorator
    async asyncMethod(a: number, b: number) {
        return a + b;
    }
}

// 处理不同类型函数的差异:
// 1. **异步函数**:通过判断函数是否为 `AsyncFunction`,如果是则使用 `await` 等待异步操作完成,以确保能正确记录执行结果。
// 2. **同步函数**:直接调用原函数并记录结果。
// 3. **类方法**:在装饰器内部通过 `apply` 方法将 `this` 上下文正确传递给原函数,确保类方法的执行环境正确。这样无论原函数是同步还是异步,都能正确处理并记录日志。