说起Nestjs的异常过滤器,不能不提.Net的全局过滤器Filter,功能那是相当的强悍,用理论话说叫AOP 面向切面编程,可谓方便了太多需要异常处理的场景。说回Nestjs的异常过滤器,实现类似的功能,采用相似的处理方式,只不过一个面向C#,一个面向Nodejs,很荣幸的我,在两个框架都找到了类似的东西。

面向切面编程AOP,是一种类似于编程规范的东东,同门师兄弟有叫面向接口编程、SOLID原则等等。

Nestjs的异常处理

默认异常处理

Nestjs内置了默认的全局异常过滤器,处理能够转换成Httpexception的异常。

如果是Httpexception或其子类异常,那么会返回该异常的JSON格式:

{"exceptionCode":40005,"message":"自定义异常","path":"/"}

如果不是Httpexception或其子类异常,那么会返回:

{"statusCode":500,"message":"Internal server error"}

由于Nestjs采用了内置的默认异常处理,因此不会出现由于出现未捕获的异常导致程序崩溃。

自定义异常过滤器处理

由于内置异常处理返回值格式无法调整,因此自定义异常就显得又为正常。自定义异常可以使返回异常信息自定义,且可以增加自定义异常编码,方便客户端人员根据异常编码进行不同的展示。

如何自定义异常?

不重复造轮子是程序员的自我约束,首先我们新建我们自己的异常基类:

import { HttpException } from "@nestjs/common";

/**
 * 定义基础异常类
 *
 * @export
 * @class BaseException
 * @extends {HttpException}
 */
export class BaseException extends HttpException {

  /**
   * Creates an instance of BaseException.
   * @param {number} exceptionCode 自定义异常编号
   * @param {string} errorMessage 提示信息
   * @param {number} statusCode 状态码
   * @memberof BaseException
   */
  constructor(public exceptionCode: number, public errorMessage: string, public statusCode: number) {
    super({ exceptionCode: exceptionCode, errorMessage: errorMessage }, statusCode);
  }

  /**
   * 获取自定义异常代码
   *
   * @return {*}
   * @memberof BaseException
   */
  getExceptionCode(): number {
    return this.exceptionCode;
  }

  getErrorMessage(): string {
    return this.errorMessage;
  }

  getStatusCode(): number {
    return this.statusCode;
  }
}

然后我们新建一个未授权异常类型,其中增加了自定义异常代码:

import { HttpStatus } from "@nestjs/common";
import { BaseException } from "./base.exception";

export class UnCauhtException extends BaseException {
  constructor() {
    super(40000, "系统运行异常,请联系管理员!", HttpStatus.FORBIDDEN);
  }
}

建立好了自定义异常,那么我们就需要处理未授权异常,首先新建自定义异常处理基类,请注意 此处我们使用的事Express:

import { ArgumentsHost, ExceptionFilter, HttpException } from "@nestjs/common";
import { HttpArgumentsHost } from "@nestjs/common/interfaces";
import { BaseException } from "src/exceptions/base.exception";
import { Response, Request } from "express";

/**
 * 异常基础类过滤器
 *
 * @export
 * @class BaseExceptionFilter
 * @implements {ExceptionFilter<BaseException>}
 */
export abstract class BaseExceptionFilter implements ExceptionFilter<BaseException>
{
  /**
   * 异常类捕获
   *
   * @abstract
   * @param {BaseException} exception
   * @param {ArgumentsHost} host
   * @memberof BaseExceptionFilter
   */
  abstract catch(exception: BaseException, host: ArgumentsHost);

  /**
   * 获取http请求上下文参数
   *
   * @protected
   * @param {ArgumentsHost} host
   * @return {*}
   * @memberof BaseExceptionFilter
   */
  protected getHttpContext(host: ArgumentsHost) {
    return host.switchToHttp();
  }

  /**
   * 获取http 响应参数
   *
   * @protected
   * @param {HttpArgumentsHost} httpContext
   * @return {*}
   * @memberof BaseExceptionFilter
   */
  protected getResponse(httpContext: HttpArgumentsHost): Response {
    return httpContext.getResponse<Response>();
  }

  /**
   * 获取http请求参数
   *
   * @protected
   * @param {HttpArgumentsHost} httpContext
   * @return {*}
   * @memberof BaseExceptionFilter
   */
  protected getRequest(httpContext: HttpArgumentsHost): Request {
    return httpContext.getRequest<Request>();
  }

  /**
   * 写入异常信息到客户端
   *
   * @param {ArgumentsHost} host
   * @param {BaseException} exception
   * @memberof BaseExceptionFilter
   */
  protected writeToClient(host: ArgumentsHost, exception: BaseException) {
    const ctx = this.getHttpContext(host);
    if(exception instanceof BaseException){
      this.getResponse(ctx).status(exception.statusCode).json({
        exceptionCode: exception.getExceptionCode(),
        message: exception.getErrorMessage(),
        path: this.getRequest(ctx).url
      });
    }else {
      const httpException=exception ;
      this.getResponse(ctx).status(500).json({
        message: "未处理的异常",
        path: this.getRequest(ctx).url
      });
    }

  }
}

新建未授权异常处理:

import { ArgumentsHost, Catch } from "@nestjs/common";
import { AuthException } from "src/exceptions/auth.exception";
import { BaseException } from "src/exceptions/base.exception";
import { BaseExceptionFilter } from "./base.exception.filter";

@Catch(AuthException)
export class AuthExceptionFilter extends BaseExceptionFilter
{
  constructor(){
    super();
    console.log("授权异常构造函数初始化" new Date().toISOString());
  }
  catch(exception: AuthException, host: ArgumentsHost) {
    exception.exceptionCode=40002;
    console.log("授权异常执行" new Date().toISOString());
    this.writeToClient(host,exception);
  }

}

针对未授权异常处理类,进行几点说明:

  1. 增加了Catch注解,只捕获Authexception的异常,其他类型的异常此类不进行处理
  2. 继承自定义异常处理类Baseexceptionfilter

应用范围

异常处理类可应用于method、controller、全局,甚至同一个Controller可以定义多个自定义异常类

import { Controller, ForbiddenException, Get, HttpException, HttpStatus, UseFilters } from '@nestjs/common';
import { AppService } from './app.service';
import { AuthException } from './exceptions/auth.exception';
import { BusinessException } from './exceptions/business.exception';
import { UnCauhtException } from './exceptions/uncauht.exception';
import { AuthExceptionFilter } from './filters/auth.exception.filter';
import { BusinessExceptionFilter } from './filters/business.exception.filter';


/**
 * 带有单个路由的基本控制器示例ff
 */
@UseFilters(AuthExceptionFilter,BusinessExceptionFilter)
@Controller()
export class AppController {
 constructor(private readonly appService: AppService) {}

 @Get()
 getHello(): string {
  //throw new Error("666");
  throw new BusinessException("自定义异常",HttpStatus.OK);
  throw new AuthException();
  throw new HttpException("自定义异常",HttpStatus.FORBIDDEN);
  return this.appService.getHello();
 }

 @Get("name")
 getName():string
 {
  return "guozhiqi";
 }
}

几点说明:

  1. 我们使用Usefilters注解进行异常过滤器的添加
  2. 我们在Appcontroller中定义了两种不同类型的自定义异常处理类
  3. 也就是我们Appcontroller中抛出的异常,只要是我们定义的这两种,那么都可以被正常处理。

几点疑问

Usefitlers中我们自定义的异常处理类会初始化几次?
答案:我们通过类型注册到Appcontroller的自定义异常类只会在程序初始化的时候初始化一次。也就是说程序启动之后,每个

controller、每个method定义了哪些异常处理类都已经确定。
如果我们捕获到异常,但不进行任何处理,会发生什么?
答案:如果我们的异常处理方法什么也不做,那么恭喜你,会成功的将浏览器请求hang死,因为异常未处理,那么浏览器会一直得不到响应。

多个异常之间的处理顺序如何?
答案:如果多个异常处理均可以捕获到该异常,那么只有第一个有效,也就是说异常处理类和 中间件不同,异常处理类只能其中一个处理,而中间件需要都进行处理。

Nestjs的@Usefilters 像谁?
首先从JS角度来看,像Angular,如果往后端看,最像Spring。 

Nestjs的异常处理并不复杂,复杂的是需要我们针对不同类型的异常进行处理,提取异常的共性。

参考文档:docs.nestjs.cn

到此这篇关于nestjs中异常过滤器Exceptionfilter的具体使用的文章就介绍到这了,更多相关nest 异常过滤器Exceptionfilter内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

nestjs中异常过滤器Exceptionfilter的具体使用的更多相关文章

  1. nestjs返回给前端数据格式的封装实现

    这篇文章主要介绍了nestjs返回给前端数据格式的封装实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. NestJs使用Mongoose对MongoDB操作的方法

    这篇文章主要介绍了NestJs使用Mongoose对MongoDB操作的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. Dapr+NestJs编写Pub及Sub装饰器实战示例

    这篇文章主要为大家介绍了Dapr+NestJs编写Pub及Sub装饰器的实战示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. nestjs中异常过滤器Exceptionfilter的具体使用

    这篇文章主要介绍了nestjs中异常过滤器Exceptionfilter的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. 使用NestJS开发Node.js应用的方法

    这篇文章主要介绍了使用NestJS开发Node.js应用的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  6. 如何为nestjs中的不同模块排除和包含不同的中间件?

    我的nestjs项目中有两个身份验证中间件。UserAuthMiddleware中间件工作正常,但AdminAuthMiddleware未注册管理路由。我如何解决这个问题?。我们将非常感谢您的帮助。尝试更改中间件注册的顺序yourtext

  7. 在nest.js中将jwk转换为pem

    我有一个jwk密钥,我想转换成pem:我已经尝试了jose、nodersa和jwkToPem等库,但不知为何,所有这些库都失败了,并在配置时到处抛出错误。下面是节点rsa转换的示例:

  8. 如何使用typeorm在json对象中搜索键值对

    我使用typeorm在nestjs中管理postgresql数据库。我必须在数据库中保存一个json响应,所以我将整个响应保存在一列中。

  9. 如何使用nest-js验证请求体数据数组

    我已经创建了一个批量客户创建api。我需要对必填字段进行验证,如何使用类validtor进行验证。我刚刚创建了一个请求主体,我的类型是带有字段的数据数组,并使用DTO验证请求。

  10. 雀巢+公牛的工作;无法触及消费者

    我正在开发一个大量使用bull的NestJs服务。有一段时间,一切都很好。但最近,我在所有托管环境中都遇到了一个问题——没有工作能接触到消费者。我用公牛监测器监测流量。每个队列中的每个作业都会进入活动状态,挂起约30秒,并因消息作业暂停超过允许的限制而失败。作业在沙盒进程中处理。如果jobs/handle-new-event.prrocessor.js包含以下代码然后得到的作业永远不会打印。我想这可能是Redis服务器的问题。我将感谢任何建议和指示。

随机推荐

  1. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  2. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  3. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  4. nodejs模块学习之connect解析

    这篇文章主要介绍了nodejs模块学习之connect解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. nodejs npm package.json中文文档

    这篇文章主要介绍了nodejs npm package.json中文文档,本文档中描述的很多行为都受npm-config(7)的影响,需要的朋友可以参考下

  6. 详解koa2学习中使用 async 、await、promise解决异步的问题

    这篇文章主要介绍了详解koa2学习中使用 async 、await、promise解决异步的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. Node.js编写爬虫的基本思路及抓取百度图片的实例分享

    这篇文章主要介绍了Node.js编写爬虫的基本思路及抓取百度图片的实例分享,其中作者提到了需要特别注意GBK转码的转码问题,需要的朋友可以参考下

  8. CentOS 8.2服务器上安装最新版Node.js的方法

    这篇文章主要介绍了CentOS 8.2服务器上安装最新版Node.js的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. node.js三个步骤实现一个服务器及Express包使用

    这篇文章主要介绍了node.js三个步骤实现一个服务器及Express包使用,文章通过新建一个文件展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下

  10. node下使用UglifyJS压缩合并JS文件的方法

    下面小编就为大家分享一篇node下使用UglifyJS压缩合并JS文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

返回
顶部