在NestJs中,如何统一接口返回的数据结构🙃🙃🙃

在 NestJS 或任何其他现代后端框架中统一接口返回的数据结构是一个非常好的实践,原因包括:

  1. 一致性:统一的数据结构使得前端开发者知道每次请求都会收到相同格式的响应,无论是成功还是失败。这减少了处理不同响应格式的复杂性。前端应用可以建立统一的响应处理逻辑,比如统一处理错误或解析数据。

  2. 维护性:后端代码更加整洁,因为所有的响应都遵循同样的模板或结构。当你需要添加新的功能或信息时,统一的结构使得在不破坏现有客户端代码的情况下扩展变得更加容易。

统一接口返回的数据结构提升了接口的一致性、可维护性和用户体验,同时简化了前后端的开发和协作。虽然它可能需要在项目初期投入更多的设计和开发工作,但长期来看,这是一个值得的投资。

在 NestJS 中,你可以通过几种方式来统一接口返回的数据结构:

  • 拦截器(Interceptors:可以创建一个全局拦截器来统一修改和标准化出站响应。

在 Nestjs 中实现

在 NestJS 中,拦截器提供了一种强大的方法来拦截和修改方法的入参和出参,包括对响应数据的格式进行统一处理。

首先我们创建一个文件并且创建一个类并使用 @Injectable() 装饰器标记它们:

ts 复制代码
import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from "@nestjs/common";
import { FastifyReply } from "fastify";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
import { getReasonPhrase } from "http-status-codes";
import { instanceToPlain } from "class-transformer";

function getCurrentTimestamp(): number {
  return Date.parse(new Date().toString()) / 1000;
}

@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(
    context: ExecutionContext,
    next: CallHandler<any>
  ): Observable<any> {
    // 获取Fastify的响应对象
    const response: FastifyReply = context
      .switchToHttp()
      .getResponse<FastifyReply>();

    return next.handle().pipe(
      map((originalData: any) => {
        if (
          originalData &&
          originalData.code &&
          originalData.message &&
          "data" in originalData
        ) {
          return originalData; // 如果是,直接返回
        }

        // 获取响应状态码
        const statusCode: number = response.statusCode;
        // 获取对应状态码的标准消息
        const message: string = getReasonPhrase(statusCode);

        // 构造标准响应格式
        return {
          code: statusCode,
          message: message,
          data: instanceToPlain(originalData) || null,
          timestamp: getCurrentTimestamp(),
        };
      })
    );
  }
}

在上面的这段代码中,使用 pipe()和 map()来转换从控制器返回的数据。在 map 操作符中,它检查返回的数据是否已经具有特定的格式(包含 code, message, 和 data)。如果是,就直接返回这个数据;如果不是,就构造一个新的对象包含状态码、消息、数据和时间。

如果原始数据不符合预期的格式,拦截器将构建一个标准格式的响应对象,包含以下属性:

  • code: 响应的 HTTP 状态码。
  • message: 基于状态码的标准消息。
  • data: 原始数据或 null,转换为简单的 JavaScript 对象(如果原始数据是类的实例)。
  • timestamp: 当前的 UNIX 时间戳。

创建拦截器后,你需要将其注册到你的应用中。拦截器可以全局注册(影响所有路由)或针对特定路由注册。通常是在跟路由下全局注册:

ts 复制代码
import { APP_INTERCEPTOR } from "@nestjs/core";
import { TransformInterceptor } from "./TransformInterceptor.ts";

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

这个时候,我们可以访问一下接口,获取一下数据,首先我们在 service 中是这样返回的:

在接口中访问,返回了这样的内容:

现在这样的内容就是已经被我们格式化完成了,之后返回的数据都是类似的了。

总结

通过使用拦截器,你可以有效地控制和统一 NestJS 应用中的接口响应格式,提升前后端的协同效率和用户体验。

相关推荐
变与不变8064 分钟前
css定位布局精讲
前端·css
LHICOD10 分钟前
Linux-2
java·linux·后端·jar·vmware·svm·vm
小杨互联网16 分钟前
Go 现代 CLI 工具离线镜像合集
开发语言·后端·golang·开源·go·命令行
lazy H21 分钟前
【计算机网络】第 15 篇:Java BIO、NIO 与高并发网络通信——从 Socket 理解 I/O 模型
网络·后端·tcp/ip·计算机网络·nio·408
FRing0326 分钟前
JavaScript入门到精通三十三(异常处理、call方法、apply方法、bind方法、防抖、节流)
开发语言·前端·javascript
geovindu32 分钟前
rust: Semaphore Pattern
开发语言·后端·设计模式·rust·代理模式·企业级信号量模式·同步型模式
计算机魔术师1 小时前
OpenAI 砍掉 100 亿融资目标,AI 资本市场的温度计变了
前端
jktantan2 小时前
(二)Vue 3 的 attrs 不是响应式:el-form 扩展属性同步的三种方案
前端·javascript·vue.js·element-plus
前端 贾公子2 小时前
第 5 章:Codex 从可运行程序到可交付工具
java·前端·数据库
用户360055579002 小时前
Kestrel_VLLM - 26 · 发射空档三步曲:事件计时 → nsys → 判别实验
前端