TypeScript中能否在方法装饰器声明中访问方法参数?
TypeScript中能否在方法装饰器声明中访问方法参数?
嘿,这个问题问到点子上了!我来给你拆解清楚~
首先得明确一个关键时间点:装饰器是在类的定义阶段就执行的,而方法的参数只有在方法被调用的时候才会传入。所以你直接在CacheData(mapKey: string)这个外层装饰器函数里想去拿方法参数,根本行不通——这时候方法还没被调用呢,哪来的参数呀😅
不过别担心,结合你用RxJS做缓存的场景,我们可以调整装饰器的逻辑,在方法被调用的时候去获取参数生成缓存key,这完全是可行的!
给你看看修改后的装饰器写法,适配你的需求:
// 先模拟一个缓存存储,你可以换成实际的缓存实现 const cache = new Map<string, any>(); function CacheData(defaultKey?: string) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { // 保存原方法的引用 const originalMethod = descriptor.value; // 替换原方法,在调用时获取参数 descriptor.value = function(...args: any[]) { // 这里的args就是方法调用时传入的所有参数! // 可以根据参数生成缓存key,比如用第一个参数,或者拼接所有参数 const cacheKey = defaultKey || args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg ).join(':'); // 先查缓存,有就直接返回 if (cache.has(cacheKey)) { console.log(`从缓存获取数据:${cacheKey}`); return of(cache.get(cacheKey)); } // 没有缓存就调用原方法,并存入缓存 return originalMethod.apply(this, args).pipe( tap(data => { console.log(`缓存数据:${cacheKey}`); cache.set(cacheKey, data); }) ); }; return descriptor; }; }
然后你可以这样用这个装饰器:
class ApiService { constructor(private http: HttpClient) {} // 用方法的id参数作为缓存key @CacheData() fetchUser(id: string): Observable<User> { return this.http.get<User>(`/api/users/${id}`); } // 用默认key + 参数拼接当缓存key @CacheData('product-list') fetchProducts(category: string, page: number): Observable<Product[]> { return this.http.get<Product[]>(`/api/products?category=${category}&page=${page}`); } }
这里有几个要注意的小细节:
- 替换原方法时要用普通函数(别用箭头函数),这样
this才能正确指向类的实例,不然原方法里的this.http会报错。 - 如果参数是复杂对象,直接转字符串可能会有问题,用
JSON.stringify()序列化是个办法,但要注意对象有没有循环引用,或者可以自己实现更高效的序列化方式。 - 你可以灵活控制key的生成逻辑,比如只取某几个参数,或者给参数加前缀,完全根据你的缓存需求来。
内容来源于stack exchange
相关产品推荐
相关产品推荐

