gpt4 book ai didi

dependency-injection - 如何将依赖注入(inject)与自定义装饰器集成

转载 作者:行者123 更新时间:2023-12-02 17:00:48 25 4
gpt4 key购买 nike

我正在尝试创建一个需要依赖注入(inject)的装饰器。例如:

@Injectable()
class UserService{
@TimeoutAndCache(1000)
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}

@TimeoutAndCache 返回一个新的 promise ,它执行以下操作:

  1. 如果调用时间超过 1000 毫秒,则返回拒绝,调用完成后,它会存储到 Redis(以便下次获取)。
  2. 如果调用时间小于1000ms,直接返回结果
export const TimeoutAndCache = function timeoutCache(ts: number, namespace) {
return function log(
target: object,
propertyKey: string,
descriptor: TypedPropertyDescriptor<any>,
) {
const originalMethod = descriptor.value; // save a reference to the original method
descriptor.value = function(...args: any[]) {
// pre
let timedOut = false;
// run and store result
const result: Promise<object> = originalMethod.apply(this, args);
const task = new Promise((resolve, reject) => {
const timer = setTimeout(() => {
if (!timedOut) {
timedOut = true;
console.log('timed out before finishing');
reject('timedout');
}
}, ts);
result.then(res => {
if (timedOut) {
// store in cache
console.log('store in cache');
} else {
clearTimeout(timer);
// return the result
resolve(res);
}
});
});
return task;
};
return descriptor;
};
};

我需要注入(inject)一个 RedisService 来保存计算结果。我可以将 Redis 服务注入(inject) UserService 的一种方法,但看起来有点丑陋。

最佳答案

您应该考虑使用 Interceptor 而不是自定义装饰器,因为它们在 Nest 管道中运行较早,并且默认支持依赖注入(inject)。

但是,因为您既要传递值(用于缓存超时)又要解决依赖关系,您必须使用 mixin 模式。

import {
ExecutionContext,
Injectable,
mixin,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { TestService } from './test/test.service';

@Injectable()
export abstract class CacheInterceptor implements NestInterceptor {
protected abstract readonly cacheDuration: number;

constructor(private readonly testService: TestService) {}

intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> {
// Whatever your logic needs to be

return call$;
}
}

export const makeCacheInterceptor = (cacheDuration: number) =>
mixin(
// tslint:disable-next-line:max-classes-per-file
class extends CacheInterceptor {
protected readonly cacheDuration = cacheDuration;
},
);

然后您将能够以类似的方式将拦截器应用于您的处理程序:

@Injectable()
class UserService{
@UseInterceptors(makeCacheInterceptor(1000))
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}

关于dependency-injection - 如何将依赖注入(inject)与自定义装饰器集成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54283033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com