You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestJS自定义装饰器中获取控制器函数的响应?

如何在NestJS中获取控制器的响应数据用于缓存?

首先要明确:你当前用的参数装饰器是在控制器方法执行前被调用的,这时候控制器还没生成响应数据,所以根本拿不到最终的返回结果。要获取响应数据,应该用NestJS的拦截器——它能在请求生命周期的响应阶段介入,直接拿到控制器返回的结果。

问题代码回顾

你的参数装饰器代码

import { createParamDecorator, ExecutionContext } from "@nestjs/common";

export const CacheData = createParamDecorator(
    (data: any, ctx: ExecutionContext) => {
        const request = ctx.switchToHttp().getRequest();
        console.log(request.url, request.method, 'request');
        const response = ctx.switchToHttp().getResponse();
        const reqBody = request.body;
        console.log(reqBody, 'reqBody');
        console.log(response.raw.req.data, 'response');
        console.log(response.raw.req.body, 'response');
        console.log(response.raw.data, 'response');
        console.log(response.cacheData, 'response');
    }
);

控制器使用代码

getStringsArr(
    @Headers('Authorization') auth: string,
    @Headers('Country') country = 'DK',
    @CacheData() cacheData,
): Array<string> {
  return ['Hello', 'World', '!'];
}

解决方案:用拦截器获取响应数据

拦截器可以通过CallHandler的handle()方法捕获控制器返回的响应流,在响应发送前处理数据。下面是适配你需求的缓存拦截器实现:

1. 创建缓存拦截器

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class CacheInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    // 先记录请求信息,和你之前的逻辑一致
    console.log(`${request.url} ${request.method} request`);
    console.log(request.body, 'reqBody');

    // 执行控制器方法,监听响应流
    return next.handle().pipe(
      tap((responseData) => {
        // 这里拿到的就是控制器返回的完整响应数据
        console.log(responseData, 'response data');
        
        // 在这里写你的缓存逻辑,比如把数据存入Redis或内存缓存
        // 示例:cache.set(`${request.method}:${request.url}`, responseData);
      }),
    );
  }
}

2. 在控制器中使用拦截器

可以针对单个方法注册,也可以全局注册:

方法级使用

import { UseInterceptors } from '@nestjs/common';

// ...

@UseInterceptors(CacheInterceptor)
getStringsArr(
    @Headers('Authorization') auth: string,
    @Headers('Country') country = 'DK',
): Array<string> {
  return ['Hello', 'World', '!'];
}

全局注册(可选)

如果所有路由都需要缓存逻辑,在AppModule中全局注册:

import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { CacheInterceptor } from './cache.interceptor';

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: CacheInterceptor,
    },
  ],
})
export class AppModule {}

为什么参数装饰器拿不到响应?

NestJS参数装饰器的执行时机是控制器方法调用前,此时控制器还没执行,自然不会生成响应数据。而拦截器的tap操作符会在控制器返回响应后触发,刚好能拿到最终的响应结果。

内容的提问来源于stack exchange,提问作者Mahmoud Hadad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 04:50:45