【问题标题】:How to format response before sending in Nest.js?如何在发送 Nestjs 之前格式化响应?
【发布时间】: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 响应中添加带有自定义消息的消息键?我的意思是如何使用拦截器方法实现我想要的结果。如果我们无法使用拦截器实现我想要的,那么还有其他方法吗?

标签: javascript typescript nestjs


【解决方案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 函数中调试或打印迭代器“数据”。即使我将断点放在那里,它也会显示未定义。你能帮我调试一下吗?
  • maprxjs operator。它的作用是获取从next.handle() 返回的 observable,这意味着从您的控制器返回的值(Nest 会自动生成一个 observable,因此您不必担心),然后它应该采用 data 并映射它根据我们使用返回 json 的箭头函数的新格式。如果您想console.log(data),则需要将其从立即返回 json 更改为使用单词 return,并且仅使用 {},而不是 ({})
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-16
  • 2021-02-05
  • 2020-02-25
  • 1970-01-01
相关资源
最近更新 更多