如何在发送 Nestjs 之前格式化响应?

Posted

技术标签:

【中文标题】如何在发送 Nestjs 之前格式化响应?【英文标题】:How to format response before sending in Nest.js? 【发布时间】:2020-05-28 02:23:58 【问题描述】:

我按照文档进行操作,并能够为响应映射添加拦截器。

我想要一个一致的 json 格式的响应输出。

如何使用拦截器或其他比这种方法更好的方法来实现这一点。


  "statusCode": 201,
  "message": "Custom Dynamic Message"
  "data": 
     // properties
     meta: 
  

transform.interceptor.ts

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

export interface Response<T> 
  statusCode: number;
  data: T;


@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> 
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> 
    return next
      .handle()
      .pipe(
        map((data) => (
          statusCode: context.switchToHttp().getResponse().statusCode,
          data,
        )),
      );
  

app.controller.ts

export class AppController 
      @Post('login')
      @UseGuards(AuthGuard('local'))
      @ApiOperation( summary: 'Login user' )
      @ApiBody( type: LoginDto )
      @ApiOkResponse( content:  'application/json':   )
      @UseInterceptors(TransformInterceptor)
      async login(@Request() req) 
        const result = await this.authService.login(req.user);
        return  message: 'Thank you!', result ;
      

【问题讨论】:

“比这种方法更好”是什么意思?拦截器方法有什么你不喜欢的地方吗? @JayMcDoniel 正如我之前所说。如何在 json 响应中添加带有自定义消息的消息键?我的意思是如何使用拦截器方法实现我想要的结果。如果我们无法使用拦截器实现我想要的,那么还有其他方法吗? 【参考方案1】:

如果我了解您对控制器响应和整体拦截器响应所做的事情,您可以做的是类似的事情:

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

export interface Response<T> 
  statusCode: number;
  message: string;
  data: T;


@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> 
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> 
    return next
      .handle()
      .pipe(
        map((data) => (
          statusCode: context.switchToHttp().getResponse().statusCode,
          message: data.message
          data: 
            result: data.result,
            meta:  // if this is supposed to be the actual return then replace  with data.result
          
        )),
      );
  

并让您的控制器返回message: 'Custom message', result

另一个需要更多前期但可能允许更简洁代码的选项是创建一个自定义装饰器,该装饰器反映来自类和方法的值(消息),然后在注入反射器后在拦截器中检索该值,但是同样,这需要更多的前期工作来设置。

【讨论】:

谢谢,这行得通,但你能告诉我更多关于我们在这里使用的地图功能的信息吗?因为早些时候我尝试做类似你的回答的事情,但我无法在 map 函数中调试或打印迭代器“数据”。即使我将断点放在那里,它也会显示未定义。你能帮我调试一下吗? map 是rxjs operator。它的作用是获取从next.handle() 返回的 observable,这意味着从您的控制器返回的值(Nest 会自动生成一个 observable,因此您不必担心),然后它应该采用 data 并映射它根据我们使用返回 json 的箭头函数的新格式。如果您想console.log(data),则需要将其从立即返回 json 更改为使用单词 return,并且仅使用 ,而不是 ()

以上是关于如何在发送 Nestjs 之前格式化响应?的主要内容,如果未能解决你的问题,请参考以下文章

如何从控制器在nestjs应用程序中发送错误代码?

如何在spring mvc中的操作之前发送响应

NESTJS 网关/Websocket - 如何通过 socket.emit 发送 jwt access_token

Camel-netty4:如何在发送下一个请求之前等待响应

如何在 NestJS 中使用多语言电子邮件模板?

如何在 Nestjs 中创建 mongodb 连接提供程序