前言

在实际开发中,为了保持接口的一致性和易于维护,我们通常会定义一个标准的接口响应格式。这种格式不仅有助于前端开发者理解接口返回的数据结构,也方便后端开发者统一管理接口的响应逻辑。

定义响应状态码枚举

为了统一管理接口的响应状态码,我们可以在项目中创建一个枚举文件。这样做的好处是,所有的状态码都在一个地方定义,方便查找和维护。

创建响应码枚举文件

  1. src 目录中新建 enums/index.ts 文件,并定义响应码和提示信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 响应码枚举
*/
export enum RESPONSE_CODE {
NOSUCCESS = -1, // 表示请求成功,但操作未成功
SUCCESS = 200, // 请求成功
BAD_REQUEST = 400, // 请求参数错误
UNAUTHORIZED = 401, // 未授权
FORBIDDEN = 403, // 禁止访问
NOT_FOUND = 404, // 资源未找到
INTERNAL_SERVER_ERROR = 500, // 服务器错误
}

/**
* 请求提示语枚举
*/
export enum RESPONSE_MSG {
SUCCESS = '请求成功',
FAILURE = '请求失败',
BAD_REQUEST = '请求参数错误',
UNAUTHORIZED = '未授权',
FORBIDDEN = '禁止访问',
NOT_FOUND = '资源未找到',
INTERNAL_SERVER_ERROR = '服务器错误',
}

创建响应拦截器

拦截器允许我们拦截传入的请求或传出的响应,并对其进行处理。我们可以创建一个响应拦截器来统一格式化所有的响应数据。

创建响应拦截器文件

在 src/common 目录中新建 response.ts 文件,并创建一个响应拦截器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { CallHandler, NestInterceptor } from '@nestjs/common';
import { map, Observable } from 'rxjs';
import { RESPONSE_CODE, RESPONSE_MSG } from '../enums';

interface Data<T> {
data: T;
}

export class ResponseInterceptor<T> implements NestInterceptor<T, Data<T>> {
intercept(context, next: CallHandler): Observable<Data<T>> {
return next.handle().pipe(map(data => ({
data,
code: RESPONSE_CODE.SUCCESS,
msg: RESPONSE_MSG.SUCCESS,
timestamp: new Date().getTime(), // 使用时间戳而非本地化时间字符串
})));
}
}

应用响应拦截器

为了使响应拦截器在整个应用程序中生效,我们需要在主应用程序模块中注册它。

在主应用程序中注册响应拦截器

在 main.ts 文件中引入并注册响应拦截器:

1
2
3
4
5
6
7
8
9
10
11
12
13
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ResponseInterceptor } from './common/response';

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

// 注册响应拦截器
app.useGlobalInterceptors(new ResponseInterceptor());

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

总结

通过定义响应状态码枚举和创建响应拦截器,我们可以确保应用程序的所有接口都返回统一格式的响应。这不仅提高了代码的可维护性,也使得前端开发者能够更容易地处理接口响应。