Skip to content

nestjs 常用代码片段

开发常用模块安装

bcrypt 依赖 python 环境,可以使用 bcryptjs 代替

bash
pnpm i @nestjs/passport passport passport-local @nestjs/jwt passport-jwt bcrypt @nestjs/swagger prisma-binding @prisma/client mockjs @nestjs/config class-validator class-transformer lodash dayjs
bash
pnpm i -D @swc/cli @swc/core @types/passport-local @types/passport-jwt @types/bcrypt prisma @types/lodash @types/dayjs

跨域问题解决

ts
app.enableCors()

添加 api 版本

效果: v1/xxx

ts
app.enableVersioning({ defaultVersion: '1', type: VersioningType.URI })

全局 api 前缀

效果: api/xxx

ts
app.setGlobalPrefix('api')

与 api 版本一起使用效果: api/v1/xxx

统一返回格式

目标返回结果

json
{
    data, // 数据
    status: 0, // 接口状态值
    extra: {}, // 拓展信息
    message: 'success', // 异常信息
    success:true // 接口业务返回状态
}

transform.interceptor.ts

ts
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'
import { map } from 'rxjs/operators'

import type { Observable } from 'rxjs'

interface Response<T> {
  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 => ({
        data,
        status: 0,
        extra: {},
        message: 'success',
        success: true,
      })),
    )
  }
}

main.ts

ts
app.useGlobalInterceptors(new TransformInterceptor())

全局异常拦截

被动异常处理

base.exception.filter.ts

ts
import { ArgumentsHost, Catch, ExceptionFilter, HttpStatus, ServiceUnavailableException } from '@nestjs/common'

@Catch()
export class AllExceptionFilter implements ExceptionFilter {
  catch(exception: Error, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const response = ctx.getResponse()
    const request = ctx.getRequest()

    request.log.error(exception)

    response.status(HttpStatus.SERVICE_UNAVAILABLE).send({
      statusCode: HttpStatus.SERVICE_UNAVAILABLE,
      timestamp: new Date().toISOString(),
      path: request.url,
      message: new ServiceUnavailableException().getResponse(),
    })
  }
}

http.exception.filter.ts

ts
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common'

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const response = ctx.getResponse()
    const request = ctx.getRequest()
    const status = exception.getStatus()

    response.status(status).send({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message: exception.getResponse(),
    })
  }
}

main.ts

ts
app.useGlobalInterceptors(new TransformInterceptor())
app.useGlobalFilters(new AllExceptionFilter(), new HttpExceptionFilter())

主动抛出异常处理

有时我们可以预见代码出现错误,会主动抛出异常,下面代码是对主动抛出指定异常时的处理

business.exception.ts

ts
import { HttpException, HttpStatus } from '@nestjs/common'
import { BUSINESS_ERROR_CODE } from './business.error'

interface BusinessError {
  code: number
  message: string
}

export class BusinessException extends HttpException {
  constructor(err: BusinessError | string) {
    if (typeof err === 'string') {
      err = {
        code: BUSINESS_ERROR_CODE.COMMON,
        message: err,
      }
    }
    super(err, HttpStatus.OK)
  }

  static throwForbidden() {
    throw new BusinessException({
      code: BUSINESS_ERROR_CODE.ACCESS_FORBIDDEN,
      message: '抱歉,您无此权限',
    })
  }
}

自定义业务错误代码

ts
export const BUSINESS_ERROR_CODE = {
  // 公共错误码
  COMMON: 10001,
  // 特殊错误码
  TOKEN_INVALID: 10002,
  // 禁止访问
  ACCESS_FORBIDDEN: 10003,
  // 权限已禁用
  PERMISSION_DISABLED: 10003,
  // 用户已冻结
  USER_DISABLED: 10004,
}

改造 http.exception.filter.ts

ts
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common'

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const response = ctx.getResponse()
    const request = ctx.getRequest()
    const status = exception.getStatus()

    if (exception instanceof BusinessException) {
      const error = exception.getResponse()
      response.status(HttpStatus.OK).send({
        data: null,
        status: error.code,
        extra: {},
        message: error.message,
        success: false,
      })
      return
    }

    response.status(status).send({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message: exception.getResponse(),
    })
  }
}

在应用程序中抛出异常示例

ts
@Get('error')
errorFunc(){
  const a = {}
  try{
    console.log(a.b)
  }catch(){
    throw new BusinessException('参数错误')
  }
}