Nest.js 框架异常处理

class Nest.js,异常处理

在开发过程中,异常处理是确保应用稳定性和用户体验的重要部分。Nest.js 提供了灵活的异常处理机制,允许开发者捕获和处理应用中的错误。以下将详细介绍如何在 Nest.js 中实现全局异常过滤器和自定义异常处理。

1. 异常处理概述

Nest.js 通过 HttpException 类来处理 HTTP 异常。可以直接抛出异常,Nest 会自动捕获并将其转换为适当的 HTTP 响应。除此之外,开发者还可以创建自定义的异常过滤器来处理更复杂的情况。

2. 全局异常过滤器

全局异常过滤器允许开发者定义一个统一的异常处理逻辑,能够捕获应用中的所有异常。可以通过实现 ExceptionFilter 接口来创建一个自定义的全局异常过滤器。

2.1 创建全局异常过滤器

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

@Catch() // 捕获所有异常
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception instanceof HttpException ? exception.getStatus() : 500;

    const message = exception instanceof HttpException ? exception.getResponse() : { message: 'Internal server error' };

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message,
    });
  }
}

2.2 注册全局异常过滤器

可以在应用的根模块中全局注册异常过滤器。

import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { AllExceptionsFilter } from './common/filters/all-exceptions.filter';
import { UsersModule } from './users/users.module';

@Module({
  imports: [UsersModule],
  providers: [
    {
      provide: APP_FILTER,
      useClass: AllExceptionsFilter,
    },
  ],
})
export class AppModule {}

3. 自定义异常处理

Nest.js 允许开发者定义自定义异常。可以扩展 HttpException 类,并在应用中抛出该异常。

3.1 创建自定义异常

import { HttpException, HttpStatus } from '@nestjs/common';

export class UserNotFoundException extends HttpException {
  constructor() {
    super('User not found', HttpStatus.NOT_FOUND);
  }
}

3.2 在控制器中使用自定义异常

在控制器中,可以根据需要抛出自定义异常。

import { Controller, Get, Param, NotFoundException } from '@nestjs/common';
import { UsersService } from './users.service';
import { UserNotFoundException } from './exceptions/user-not-found.exception';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get(':id')
  getUserById(@Param('id') id: string) {
    const user = this.usersService.findOne(id);
    if (!user) {
      throw new UserNotFoundException(); // 抛出自定义异常
    }
    return user;
  }
}

4. 结合其他组件使用异常处理

在实际开发中,通常会结合中间件、管道等组件使用异常处理。例如,在管道中验证数据时,若数据无效,可以抛出异常。

4.1 使用管道抛出异常

import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';

@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    if (!value.name) {
      throw new BadRequestException('Name is required'); // 抛出异常
    }
    return value;
  }
}

4.2 在控制器中使用管道

可以在控制器中使用上述验证管道,确保请求体数据有效。

import { Controller, Post, Body, UsePipes } from '@nestjs/common';
import { UsersService } from './users.service';
import { ValidationPipe } from './pipes/validation.pipe';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  @UsePipes(new ValidationPipe()) // 使用管道
  createUser(@Body() createUserDto: any) {
    return this.usersService.create(createUserDto);
  }
}

5. 处理异步异常

Nest.js 还可以处理异步操作中的异常。例如,在使用 Promise 时,可以捕获异步异常。

5.1 异步操作示例

import { Injectable } from '@nestjs/common';

@Injectable()
export class UsersService {
  private users = [];

  async findUserById(id: string) {
    const user = this.users.find(user => user.id === id);
    if (!user) {
      throw new UserNotFoundException(); // 抛出自定义异常
    }
    return user;
  }
}

5.2 在控制器中调用异步方法

import { Controller, Get, Param } from '@nestjs/common';
import { UsersService } from './users.service';
import { UserNotFoundException } from './exceptions/user-not-found.exception';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get(':id')
  async getUserById(@Param('id') id: string) {
    return await this.usersService.findUserById(id);
  }
}

6. 其他异常类型处理

Nest.js 还提供了一些内置的异常类,例如 NotFoundExceptionBadRequestException 等,可以根据需要直接使用。

import { Controller, Get, Param, NotFoundException } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get(':id')
  getUserById(@Param('id') id: string) {
    // 直接使用内置异常
    throw new NotFoundException(`User with ID ${id} not found`);
  }
}

总结

Nest.js 提供了强大的异常处理机制,通过全局异常过滤器和自定义异常,可以灵活地处理应用中的错误。结合管道和中间件等组件,可以实现更为复杂的异常处理逻辑。通过合理的异常处理,不仅可以提高应用的稳定性,还可以改善用户体验。使用全局过滤器时,开发者可以统一管理异常响应,使代码更加整洁。通过上述示例,我们展示了如何在 Nest.js 中有效地实现异常处理,从而提升应用的可靠性和可维护性。

评论区
评论列表
menu