Nest.js中的Interceptor,Middleware和Filter之间有什么区别?

时间:2019-02-25 10:01:29

标签: node.js typescript nestjs

Nest.js框架中的拦截器,过滤器和中间件有什么区别?什么时候应该使用它们中的一个并使其比另一个更受青睐?

谢谢

3 个答案:

答案 0 :(得分:11)

正如您已经暗示的问题一样,这三个概念都是非常相似的,在很多情况下,很难决定并取决于您的偏好。但我可以概述一下这些差异:

Interceptors

拦截器可以在之前和在调用路由处理程序之后访问响应/请求。

注册

  • 直接在控制器类中,使用@UseInterceptors()控制器或方法范围的
  • app.useGlobalInterceptors()中的main.ts全局

示例

  • LoggingInterceptor:在路由处理程序之前以及之后的结果中请求。测量时间。
  • ResultMapping:将null转换为[]或将结果包装在响应对象中:users-> {users: users}

结论

我喜欢与中间件相比,注册更靠近路由处理程序。但是存在一些限制,例如,当在路由处理程序中将response@Res()对象一起使用时,您将无法设置响应代码,也无法使用拦截器。

Middleware

仅在调用路由处理程序之前调用中间件。您可以访问响应对象,但没有路由处理程序的结果。它们基本上是表达的中间件功能。

注册

  • 在该模块中,非常灵活的方式来选择相关路由(使用通配符,按方法...)
  • app.use()中的main.ts全局

示例

  • FrontendMiddleware:将除API外的所有路由重定向到index.html,请参阅article
  • 您可以使用任何现成的快速中间件。有很多个库,例如body-parsermorgan

结论

中间件的注册非常灵活,例如:应用于除一条路径之外的所有路由。但是,由于它们已在模块中注册,因此当您查看其方法时,您可能不会意识到它适用于您的控制器。可以利用现有的所有快速中间件库也很棒。

Exception Filters

异常过滤器在路由处理程序和拦截器之后调用。它们是在响应消失之前最后进行更改的地方。

注册

  • 直接在控制器类中,使用@UseFilters()控制器或方法范围的
  • 在您的app.useGlobalFilters()中全局main.ts

示例

  • UnauthorizedFilter:映射为用户易于理解的消息
  • NotFoundFilter:将所有未找到的路由(不是您的api的一部分)映射到您的index.html

结论

异常过滤器的基本用例提供了可以理解的错误消息(隐藏技术细节)。但是,还有其他创造性的使用方式:当您为单个页面应用程序提供服务时,通常,所有路径都应重定向到index.html,API路径除外。在这里,您可以在NotFoundException上重定向。有些人可能会发现这个聪明的人很hacky。你的选择。 ;-)


因此执行顺序为:

中间件->拦截器->路由处理程序->拦截器->异常过滤器(如果引发异常)

使用这三个函数,您可以在其构造函数中注入其他依赖项(例如服务,...)。

答案 1 :(得分:4)

对于我们这些从视觉上更好地获得它的人,我基于最新的v6.10版本创建了这个NestJs管道图。请随时指出任何不正确之处。如有需要,我会立即进行审核和更新。

enter image description here

答案 2 :(得分:2)

我假设您的意思是管道而不是过滤器,因为过滤器主要与异常处理相关。

由于中间件是组成任何Web应用程序的灵活方式,但肯定有一些重叠,但更多地是通用概念(创建功能栈以构建管道)。其他的则是Nest特定的概念,因此与诸如Dependency Injection之类的关系更加自然。

管道用于转换输入数据(并可选地进行验证)。

拦截器真的很整洁,因为它们可以转换进出API的数据。它们使您能够通过使用可观察的流来改变原始处理程序将返回的内容。这可能是您需要使用两个中间件(在处理程序的两侧)实现的。

当您要转换传入处理程序的数据时,请使用管道。

当需要双向转换时,请使用拦截器。

当您想要更接近于传统的(例如Express)构建Web应用程序的方式时,或者当您想一次将功能广泛地应用于许多处理程序时(使用更少的装饰器在代码中浮动),请使用中间件。 / p>