在 Nest.js 中发送之前如何格式化响应?

Ist*_*lor 11 javascript typescript nestjs

我遵循了文档,并且能够为响应映射添加一个拦截器。

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

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

{
  "statusCode": 201,
  "message": "Custom Dynamic Message"
  "data": {
     // properties
     meta: {}
  }
}
Run Code Online (Sandbox Code Playgroud)

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,
        })),
      );
  }
}
Run Code Online (Sandbox Code Playgroud)

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 };
      }
}
Run Code Online (Sandbox Code Playgroud)

Jay*_*iel 16

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

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
          }
        })),
      );
  }
}
Run Code Online (Sandbox Code Playgroud)

并使您的控制器返回为{message: 'Custom message', result}.

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

  • `map` 是 [rxjs 运算符](https://www.learnrxjs.io/learn-rxjs/operators/transformation/map)。它的作用是获取从“next.handle()”返回的可观察值,这意味着从控制器返回的值(Nest 自动生成可观察值,因此你不需要担心这一点),然后它应该获取“data” ` 并使用返回 json 的箭头函数将其相应地映射到我们的新格式。如果您想要 `console.log(data)`,您需要将其从立即返回 json 更改为使用单词 `return` 并且仅使用 `{}`,而不是 `({})` (2认同)