MST
星途 面试题库

面试题:TypeScript参数装饰器在AOP(面向切面编程)中的深度应用

基于TypeScript,利用参数装饰器实现一个AOP功能,要求能够在函数调用前后执行一些通用逻辑,例如记录函数调用的参数、时间以及执行结果,并且要考虑如何处理异步函数。请详细阐述设计方案,并给出可运行的完整代码示例,同时说明这种实现方式相较于传统AOP实现方式的优缺点。
29.5万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计方案

  1. 参数装饰器定义:在TypeScript中,参数装饰器会在运行时被调用,并且传入目标类的原型、方法名以及参数在参数列表中的索引。
  2. 通用逻辑实现:在装饰器内部,我们可以通过闭包的方式来记录函数调用的参数、时间,并在函数执行前后执行特定逻辑。
  3. 异步函数处理:使用asyncawait来处理异步函数,确保在异步操作完成后记录执行结果。

完整代码示例

function logParameter(target: any, propertyKey: string, parameterIndex: number) {
    return function (originalMethod: Function) {
        return function (...args: any[]) {
            const startTime = new Date();
            console.log(`Calling function ${propertyKey} at ${startTime.toISOString()}`);
            console.log(`Parameter at index ${parameterIndex} is:`, args[parameterIndex]);

            const result = originalMethod.apply(this, args);

            if (typeof result.then === 'function') {
                return result.then((resolvedResult: any) => {
                    const endTime = new Date();
                    console.log(`Function ${propertyKey} finished at ${endTime.toISOString()}`);
                    console.log(`Execution result is:`, resolvedResult);
                    return resolvedResult;
                });
            } else {
                const endTime = new Date();
                console.log(`Function ${propertyKey} finished at ${endTime.toISOString()}`);
                console.log(`Execution result is:`, result);
                return result;
            }
        };
    };
}

class MyClass {
    async myMethod(@logParameter param: string) {
        // 模拟异步操作
        await new Promise(resolve => setTimeout(resolve, 1000));
        return `Processed: ${param}`;
    }
}

const myObj = new MyClass();
myObj.myMethod('test').then(console.log);

相较于传统AOP实现方式的优缺点

优点

  1. 简洁性:TypeScript的装饰器语法糖使得代码更加简洁,逻辑清晰。在上述代码中,通过一个简单的装饰器函数就实现了AOP功能。
  2. 紧密集成:与TypeScript语言特性紧密结合,在面向对象编程的基础上轻松实现AOP,对于TypeScript项目而言更易维护和扩展。

缺点

  1. 兼容性:装饰器是ES7的提案,虽然TypeScript支持,但在一些老版本的JavaScript环境中可能不兼容,需要额外的编译或运行时处理。
  2. 调试难度:由于装饰器通过闭包和函数劫持来实现,在调试复杂的AOP逻辑时,可能需要花费更多精力去理解装饰器内部的执行流程。