Nest.js 实战 (一):使用过滤器优雅地统一处理响应体

news2024/9/23 19:21:47

前言

在我们实际的业务开发中,我们可以看到后端接口返回格式都有一定的要求,假如我们统一规定接口的统一返回格式为:

{
  data: any; // 业务数据
  code: number; // 状态码
  msg: string; // 响应信息
  timestamp: number; // 时间戳
}

那么在 Nest.js 中,我们应该如何处理呢?

定义响应状态码枚举和类型

  1. src 目录中新建 /enums/index.ts 文件:
 /**
 * @description: 响应码
 */
 export enum RESPONSE_CODE {
   NOSUCCESS = -1, // 表示请求成功,但操作未成功
   SUCCESS = 200, // 请求成功
   BAD_REQUEST = 400, // 请求错误
   UNAUTHORIZED = 401, // 未授权
   FORBIDDEN = 403, // 禁止访问
   NOT_FOUND = 404, // 资源未找到
   INTERNAL_SERVER_ERROR = 500, // 服务器错误
 }

 /**
 * @description: 请求提示语
 */
 export enum RESPONSE_MSG {
   SUCCESS = '请求成功',
   FAILURE = '请求失败',
 }
  1. src 目录中新建 /typings/index.d.ts 文件:
declare namespace Api {
 namespace Common {
   /**
    * @description: 全局响应体
    */
   type Response<T = any> = {
     code: number; // 状态码
     data?: T; // 业务数据
     msg: string; // 响应信息
     timestamp: number; // 时间戳
   };
   /**
    * @description: 分页数据
    */
   type PageResponse<T = any> = {
     current?: number; // 页码
     size?: number; // 当前页条数
     total?: number; // 总条数
     records: T[]; // 业务数据
   };
 }
}
  1. 我们可以编写一个公共方法,专门处理接口的返回结果:
  import dayjs from 'dayjs';

 import { RESPONSE_CODE, RESPONSE_MSG } from '@/enums';
 import type { Response } from '@/types';

 /**
  * @description: 统一返回体
  */
 export const responseMessage = <T = any>(
   data,
   msg: string = RESPONSE_MSG.SUCCESS,
   code: number = RESPONSE_CODE.SUCCESS,
 ): Response<T> => ({ data, msg, code, timestamp: dayjs().valueOf() });

这里大家可以根据自己的实际业务需求修改。

定义响应体 DTO

首先,定义一个统一的响应数据传输对象(DTO),这将作为所有 API 响应的基本结构。

src 目录中新建 /dto/response.dto.ts 文件:

import { ApiProperty } from '@nestjs/swagger';

import { RESPONSE_CODE, RESPONSE_MSG } from '@/enums';

export class ResponseDto {
  @ApiProperty({
    type: Number,
    description: '业务状态码',
    default: RESPONSE_CODE.SUCCESS,
  })
  code: number;

  @ApiProperty({
    type: String,
    description: '业务信息',
    default: RESPONSE_MSG.SUCCESS,
  })
  msg: string;

  @ApiProperty({ description: '业务数据' })
  data?: any;

  @ApiProperty({ type: Number, description: '时间戳', default: 1720685424078 })
  timestamp: number;
}

HttpException 异常过滤器

创建一个异常过滤器,它负责捕获作为 HttpException 类实例的异常,并为它们设置自定义响应逻辑。

src 目录中新建 /filter/http-exception.filter.ts 文件:

  import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common';
  import { Response } from 'express';

  import { responseMessage } from '@/utils';

  // @Catch() 装饰器绑定所需的元数据到异常过滤器上。它告诉 Nest这个特定的过滤器正在寻找
  @Catch(HttpException)
  export class HttpExceptionsFilter implements ExceptionFilter {
    catch(exception: HttpException, host: ArgumentsHost) {
      // 获取上下文
      const ctx = host.switchToHttp();
      // 获取响应体
      const response = ctx.getResponse<Response>();
      // 获取状态码
      const statusCode = exception.getStatus();

      // 自定义异常返回体
      response.status(statusCode).json(responseMessage(null, exception.message, statusCode));
    }
 }

全局异常过滤器

创建一个全局异常过滤器来处理所有的异常,并将其转换为统一的响应格式。

src 目录中新建 /filter/all-exception.filter.ts 文件:

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { Response } from 'express';

import { responseMessage } from '@/utils';

// @Catch() 装饰器绑定所需的元数据到异常过滤器上。它告诉 Nest这个特定的过滤器正在寻找
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    // 获取上下文
    const ctx = host.switchToHttp();
    // 获取响应体
    const response = ctx.getResponse<Response>();
    // 获取状态码,判断是HTTP异常还是服务器异常
    const statusCode =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    // 自定义异常返回体
    response
      .status(statusCode)
      .json(responseMessage(null, '服务器内部错误!', statusCode));
  }
}

全局配置

main.ts 中注册全局的异常过滤器。

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AllExceptionsFilter } from '@/filter/all-exception.filter'; // 全局异常过滤器
import { HttpExceptionsFilter } from '@/filter/http-exception.filter'; // http 异常过滤器

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // 错误异常捕获 和 过滤处理
  app.useGlobalFilters(new AllExceptionsFilter());
  app.useGlobalFilters(new HttpExceptionsFilter());

  await app.listen(3000);
}
bootstrap();

效果预览

  1. 正常请求成功
    在这里插入图片描述

  2. 当我们访问一个不存在的接口时
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1929787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】:时间和空间复杂度

目录 如何衡量一个代码的好坏 时间复杂度 概念 计算方法 实例计算 【实例1】 【实例2】 【实例3】 【实例4】&#xff1a;冒泡排序的时间复杂度 【实例5】&#xff1a;二分查找的时间复杂度 【实例6】&#xff1a;阶乘递归的时间复杂度 【实例7】&#xff1a;斐波那契…

昇思25天学习打卡营第22天|GAN图像生成

今天是参加昇思25天学习打卡营的第22天&#xff0c;今天打卡的课程是“GAN图像生成”&#xff0c;这里做一个简单的分享。 1.简介 今天来学习“GAN图像生成”&#xff0c;这是一个基础的生成式模型。 生成式对抗网络(Generative Adversarial Networks&#xff0c;GAN)是一种…

springboot系列九: 接收参数相关注解

文章目录 基本介绍接收参数相关注解应用实例PathVariableRequestHeaderRequestParamCookieValueRequestBodyRequestAttributeSessionAttribute 复杂参数基本介绍应用实例 自定义对象参数-自动封装基本介绍应用实例 ⬅️ 上一篇: springboot系列八: springboot静态资源访问&…

02-Redis未授权访问漏洞

免责声明 本文仅限于学习讨论与技术知识的分享&#xff0c;不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;本文作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担&…

【Windows】Microsoft PC Manager

使用 Microsoft PC Manager&#xff0c;用户可以轻松执行基本的计算机维护&#xff0c;并通过一键操作提升设备速度。这款应用程序提供了一系列功能&#xff0c;包括磁盘清理、启动应用管理、病毒扫描、Windows 更新检查、进程监控和存储管理。 Microsoft PC Manager 的关键特…

React学习笔记03-----手动创建和运行

一、项目创建与运行【手动】 react-scripts集成了webpack、bable、提供测试服务器 1.目录结构 public是静态目录&#xff0c;提供可以供外部直接访问的文件&#xff0c;存放不需要webpack打包的文件&#xff0c;比如静态图片、CSS、JS src存放源码 &#xff08;1&#xff09…

xss复习总结及ctfshow做题总结xss

xss复习总结 知识点 1.XSS 漏洞简介 ​ XSS又叫CSS&#xff08;Cross Site Script&#xff09;跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中Web里面的Script代码会被执行&#xff0c;从而达到恶意攻击用户的…

ASF平台

最近一直在研究滑坡&#xff0c;但是insar数据处理很麻烦&#xff0c;自己手动处理gamma有很慢&#xff0c;而且据师兄说&#xff0c;gamma处理还很看经验&#xff0c;我就又去看了很多python库和其他工具: isce mintpy pyint 也使用了asf上面的处理产品&#xff0c;虽然也…

H. Beppa and SwerChat【双指针】

思路分析&#xff1a;运用双指针从后往前扫一遍&#xff0c;两次分别记作数组a&#xff0c;b&#xff0c;分别使用双指针i和j来扫&#xff0c;如果一样就往前&#xff0c;如果不一样&#xff0c;i–,ans #include<iostream> #include<cstring> #include<string…

C#绘制含流动块的管道

1&#xff0c;效果。 2&#xff0c;绘制技巧。 1&#xff0c;流动块的实质是使用Pen的自定义DashStyle绘制的线&#xff0c;并使用线的偏移值呈现出流动的效果。 Pen barPen new Pen(BarColor, BarHeight);barPen.DashStyle DashStyle.Custom;barPen.DashOffset startOffse…

解读InnoDB数据库索引页与数据行的紧密关联

目录 一、快速走进索引页结构 &#xff08;一&#xff09;整体展示说明 &#xff08;二&#xff09;内容说明 File Header&#xff08;文件头部&#xff09; Page Header&#xff08;页面头部&#xff09; Infimum Supremum&#xff08;最小记录和最大记录&#xff09; …

太速科技-FMC207-基于FMC 两路QSFP+光纤收发子卡

FMC207-基于FMC 两路QSFP光纤收发子卡 一、板卡概述 本卡是一个FPGA夹层卡&#xff08;FMC&#xff09;模块&#xff0c;可提供高达2个QSFP / QSFP 模块接口&#xff0c;直接插入千兆位级收发器&#xff08;MGT&#xff09;的赛灵思FPGA。支持利用Spartan-6、Virtex-6、Kin…

Webpack看这篇就够了

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

java.sql.SQLException: Unknown system variable ‘query_cache_size‘【Pyspark】

1、问题描述 学习SparkSql中&#xff0c;将spark中dataframe数据结构保存为jdbc的格式并提交到本地的mysql中&#xff0c;相关代码见文章末尾。 运行代码时报出相关配置文件错误&#xff0c;如下。 根据该报错&#xff0c;发现网络上多数解决方都是基于java开发的解决方案&a…

GPT-4从0到1搭建一个Agent简介

GPT-4从0到1搭建一个Agent简介 1. 引言 在人工智能领域&#xff0c;Agent是一种能够感知环境并采取行动以实现特定目标的系统。本文将简单介绍如何基于GPT-4搭建一个Agent。 2. Agent的基本原理 Agent的核心是感知-行动循环&#xff08;Perception-Action Loop&#xff09;…

【Windows】系统盘空间不足?WizTree 和 DISM++ 来帮忙

当您的系统盘空间接近饱和时&#xff0c;了解硬盘空间的使用情况变得尤为重要。在这种情况下&#xff0c;您可以利用 Windows 内置的存储使用工具来快速查看哪些文件和应用程序占用了大量空间&#xff0c;并采取相应措施进行清理。此外&#xff0c;第三方工具如 WizTree 可以提…

Java NIO合并多个文件

NIO API java.nio (Java Platform SE 8 ) 直接上代码 package com.phil.aoplog.util;import lombok.extern.slf4j.Slf4j;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel;Slf4j public…

勒索防御第一关 亚信安全AE防毒墙全面升级 勒索检出率提升150%

亚信安全信舷AE高性能防毒墙完成能力升级&#xff0c;全面完善勒索边界“全生命周期”防御体系&#xff0c;筑造边界勒索防御第一关&#xff01; 勒索之殇&#xff0c;银狐当先 当前勒索病毒卷携着AI技术&#xff0c;融合“数字化”的运营模式&#xff0c;形成了肆虐全球的网…

数据结构进阶:使用链表实现栈和队列详解与示例(C, C#, C++)

文章目录 1、 栈与队列简介栈&#xff08;Stack&#xff09;队列&#xff08;Queue&#xff09; 2、使用链表实现栈C语言实现C#语言实现C语言实现 3、使用链表实现队列C语言实现C#语言实现C语言实现 4、链表实现栈和队列的性能分析时间复杂度空间复杂度性能特点与其他实现的比较…

VBA学习(21):遍历文件夹(和子文件夹)中的文件

很多时候&#xff0c;我们都想要遍历文件夹中的每个文件&#xff0c;例如在工作表中列出所有文件名、对每个文件进行修改。VBA给我们提供了一些方式&#xff1a;&#xff08;1&#xff09;Dir函数&#xff1b;&#xff08;2&#xff09;File System Object。 使用Dir函数 Dir…