Dependency injection 如何将依赖项注入与自定义装饰器集成

Dependency injection 如何将依赖项注入与自定义装饰器集成,dependency-injection,nestjs,Dependency Injection,Nestjs,我正在尝试创建一个需要依赖注入的装饰器。 例如: @Injectable() class UserService{ @TimeoutAndCache(1000) async getUser(id:string):Promise<User>{ // Make a call to db to get all Users } } @Injectable() 类用户服务{ @TimeoutAndCache(1000) 异步getUser(id:string):承诺{

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

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

@Injectable()
类用户服务{
@TimeoutAndCache(1000)
异步getUser(id:string):承诺{
//调用db以获取所有用户
}
}
@TimeoutAndCache返回一个新的承诺,它执行以下操作:

  • 如果调用耗时超过1000毫秒,则返回拒绝,当调用完成时,将存储到redis(以便下次可以获取)
  • 如果调用时间少于1000毫秒,只需返回结果
  • export const TimeoutAndCache=函数timeoutCache(ts:编号,命名空间){
    返回函数日志(
    目标:目标,,
    propertyKey:字符串,
    描述符:TypedPropertyDescriptor,
    ) {
    const originalMethod=descriptor.value;//保存对原始方法的引用
    descriptor.value=函数(…参数:任意[]){
    //前
    设timedOut=false;
    //运行并存储结果
    const result:Promise=originalMethod.apply(这是args);
    const task=新承诺((解决、拒绝)=>{
    常量计时器=设置超时(()=>{
    如果(!timedOut){
    timedOut=true;
    console.log('完成前超时');
    拒绝(“timedout”);
    }
    },ts);
    结果。然后(res=>{
    if(timedOut){
    //存储在缓存中
    log(“存储在缓存中”);
    }否则{
    清除超时(计时器);
    //返回结果
    决议(res);
    }
    });
    });
    返回任务;
    };
    返回描述符;
    };
    };
    
    我需要注入一个RedisService来保存计算结果。
    有一种方法可以将Redis服务注入到UserService中,但看起来有点难看

    > P>你应该考虑使用<代码>拦截器< /C>而不是自定义装饰器,因为它们在嵌套管道中运行较早,默认支持依赖注入。p> 但是,由于既要传递值(缓存超时)又要解决依赖关系,因此必须使用
    mixin
    模式

    导入{
    执行上下文,
    可注射,
    米辛,
    内斯特拦截器,
    }来自“@nestjs/common”;
    从“rxjs”导入{Observable};
    从“./test/test.service”导入{TestService};
    @可注射()
    导出抽象类CacheInterceptor实现NestInterceptor{
    受保护的摘要只读缓存持续时间:number;
    构造函数(私有只读testService:testService){}
    拦截(
    上下文:ExecutionContext,
    调用$:可观察,
    ):可见{
    //不管你的逻辑是什么
    回电$;
    }
    }
    导出常量makeCacheInterceptor=(cacheDuration:number)=>
    混合(
    //tslint:禁用下一行:每个文件的最大类数
    类扩展了CacheInterceptor{
    受保护的只读cacheDuration=cacheDuration;
    },
    );
    
    然后,您将能够以类似的方式将拦截器应用于处理程序:

    @Injectable()
    类用户服务{
    @UseInterceptors(makeCacheInterceptor(1000))
    异步getUser(id:string):承诺{
    //调用db以获取所有用户
    }
    }
    
    我很难让拦截器工作,即使是上的简单日志拦截器也不能在类中的任何方法上工作。它似乎只对@Controller注释的方法有效?您能为这个添加一个测试用例吗?@jesse carter您从哪里了解到了
    mixin
    函数?我没有在文档中看到过()
    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;
      };
    };