面试题答案
一键面试设计思路
- 性能优化:
- 缓存策略:对于频繁调用且输入参数相同会得到相同结果的方法,使用缓存来避免重复计算。可以使用一个Map来存储方法调用的输入参数和对应的返回值。
- 异步处理:对于一些可以异步执行的任务,使用
async/await
或者Promise
将其异步化,避免阻塞主线程。
- 日志记录:
- 调用链追踪:为每个请求生成一个唯一的标识符(例如
uuid
),在整个调用链中传递这个标识符,记录日志时带上它,方便追踪整个请求的流程。 - 参数和返回值记录:在方法调用前后记录方法的输入参数和返回值,便于调试和分析。
- 调用链追踪:为每个请求生成一个唯一的标识符(例如
关键代码实现
- 安装依赖:
- 首先需要安装
uuid
库用于生成唯一标识符,在项目目录下执行npm install uuid
。
- 首先需要安装
- 定义装饰器:
import { v4 as uuidv4 } from 'uuid';
// 缓存装饰器
function cache(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const cacheMap = new Map();
descriptor.value = function (...args: any[]) {
const key = args.toString();
if (cacheMap.has(key)) {
return cacheMap.get(key);
}
const result = originalMethod.apply(this, args);
cacheMap.set(key, result);
return result;
};
return descriptor;
}
// 日志记录装饰器
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const requestId = uuidv4();
console.log(`[${requestId}] Start calling method ${propertyKey} with args:`, args);
try {
const result = await originalMethod.apply(this, args);
console.log(`[${requestId}] Method ${propertyKey} returned:`, result);
return result;
} catch (error) {
console.error(`[${requestId}] Method ${propertyKey} error:`, error);
throw error;
}
};
return descriptor;
}
// 组合装饰器
function performanceAndLog(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
cache(target, propertyKey, descriptor);
return log(target, propertyKey, descriptor);
}
- 使用装饰器:
class MyService {
@performanceAndLog
async expensiveCalculation(a: number, b: number): Promise<number> {
// 模拟一些耗时操作
await new Promise(resolve => setTimeout(resolve, 1000));
return a + b;
}
}
const myService = new MyService();
myService.expensiveCalculation(1, 2).then(result => {
console.log('Final result:', result);
});
在上述代码中:
cache
装饰器实现了简单的缓存策略,根据方法的输入参数缓存返回值。log
装饰器生成唯一的请求ID,记录方法调用的开始、结束以及错误信息,实现调用链追踪和参数、返回值记录。performanceAndLog
装饰器组合了cache
和log
装饰器,先进行缓存优化,再进行日志记录。在MyService
类的expensiveCalculation
方法上使用performanceAndLog
装饰器,该方法就同时具备了性能优化和日志记录的功能。