统一响应体结构

Why?构建统一的响应体数据结构的好处是,它方便前端开发人员拦截和处理响应,提高代码可读性,并为错误处理提供统一的结构和信息,从而提升开发效率。

封装统一响应工具函数

// src/core/utils/resWrapper.util.ts
function RES_WRAPPER<T>(
  data: T,
  msg: string,
  code: number
): Common.CommonRes<T> {
  return {
    data,
    msg,
    code,
  };
}
export function SUCCESS_RES<T>(data: T, msg = "success") {
  return RES_WRAPPER(data, msg, 200);
}
export function ERROR_RES(msg: string, code = 400, data?: any) {
  return RES_WRAPPER(data, msg, code);
}
// src/modules/user/user.controller.ts
@Get('/getUserList')
getUserList(): Common.CommonRes<UserItem[]> {
  const userList = this.userService.getUserList();
  return SUCCESS_RES(userList, 'success');
}
// src/modules/user/user.controller.ts
@Get('getUserDetail/:id')
getUserDetail(
  @Param('id', GetUserDetailDto) id: string,
  @Res() res: Response,
): void {
  const targetUser = this.userService.getUserDetail(id);
  if (targetUser) {
    res.status(200).json(SUCCESS_RES(targetUser));
  } else {
    res.status(404).json(ERROR_RES('User was not found'));
  }
}

封装统一响应过滤器

  • 封装异常响应过滤器
import {
  Catch,
  HttpException,
  ExceptionFilter,
  ArgumentsHost,
} from "@nestjs/common";

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp(); // 获取请求上下文
    const response = ctx.getResponse(); // 获取请求上下文中的 response对象
    const status = exception.getStatus(); // 获取异常状态码

    // 设置错误信息
    const message = exception.message
      ? exception.message
      : `${status >= 500 ? "Service Error" : "Client Error"}`;
    const errorResponse = {
      data: {},
      message: message,
      code: -1,
    };

    // 设置返回的状态码,发送错误信息
    response.status(status).json(errorResponse);
  }
}
  • 正常响应拦截器
import {
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Injectable,
} from "@nestjs/common";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";

@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map((data) => {
        return {
          data,
          code: 0,
          msg: "请求成功",
        };
      })
    );
  }
}
  • 在 main.ts 中全局注册
import { TransformInterceptor } from "./path/to/your/interceptor";
import { HttpExceptionFilter } from "./path/to/your/filter";

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

  // 全局注册的响应过滤器
  app.useGlobalInterceptors(new TransformInterceptor());
  app.useGlobalFilters(new HttpExceptionFilter());

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

这样就可以统一的返回错误请求了,只需要抛出异常即可,比如:

throw new HttpException("User was not found", 404);