Kar*_*lam 2 dependency-injection nestjs
我正在尝试创建一个需要依赖注入的装饰器。例如:
@Injectable()
class UserService{
@TimeoutAndCache(1000)
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}
Run Code Online (Sandbox Code Playgroud)
@TimeoutAndCache 返回一个新的承诺,它执行以下操作:
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;
};
};
Run Code Online (Sandbox Code Playgroud)
我需要注入一个 RedisService 来保存评估结果。我可以将 Redis Service 注入 UserService 的一种方法,但看起来有点丑陋。
您应该考虑使用一个Interceptor而不是自定义装饰器,因为它们在 Nest 管道中运行较早,并且默认情况下支持依赖项注入。
但是,因为您既要传递值(用于缓存超时)又要解析依赖项,所以您必须使用该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;
},
);
Run Code Online (Sandbox Code Playgroud)
然后,您就可以以类似的方式将拦截器应用于您的处理程序:
@Injectable()
class UserService{
@UseInterceptors(makeCacheInterceptor(1000))
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2130 次 |
| 最近记录: |