良好的应用模块化与依赖注入(DI)创建的注射树层次结构密切相关。 DI注射器有时被称为DI容器,但是由于NestJS和Ditsmod从Angular中采取了许多概念,因此该帖子将使用“注射器”一词(因为它在Angular中)。
。在这篇文章中,Nestjs V10.0和Ditsmod v2.38用于比较。我是Ditsmod的作者。
Nestjs中的示波器
在Nestjs中,没有明确定义的DI注射器层次结构,但是有些范围隐含地指的是这样的层次结构:
-
DEFAULT
-提供商的一个实例在整个应用程序中共享。实例生命周期直接与应用程序生命周期绑定。一旦应用程序引导后,所有Singleton提供商都已实例化。默认情况下使用Singleton范围。 -
REQUEST
-专门为每个传入请求创建了提供商的新实例。该实例是在请求完成处理后将垃圾收集的。 -
TRANSIENT
-瞬态提供商并未在消费者之间共享。注入暂时提供商的每个消费者都会收到一个新的专用实例。
似乎Nestjs(V10.0)尚无在模块级别实例化提供商的能力。这导致应用模块的恶化:
- Exception filters module-scoped;
- Can I use Interceptor in Module ? What should I do?;
- Allow APP_* providers to be module-scoped rather than global.
DITSMOD中的DI注射器层次结构
ditsmod具有4个静态DI注射器层次结构:
- 应用程序级别。在申请的生命周期中,提供商仅实例化一次(这相当于Nestjs中的
DEFAULT
范围,但是在DitsMod中,这是在第一个请求中实例化的,而在Nestjs中,该实例是在应用程序启动时实例化的); ); )
- 模块级别。为每个模块创建了一次提供商实例;
- 路线级别。每个路线的提供者实例是一次创建;
- HTTP请求级别。为每个HTTP请求创建一次提供商实例(这是Nestjs中
REQUEST
范围的等效)。
此外,在这些级别中的每个级别中,Ditsmod都能在不使用喷油器缓存的情况下每次创建特定提供商的新实例时(实际上,这相当于Nestjs中的TRANSIENT
范围)。 P>
内斯特控制器的功能
默认情况下,Nestjs将控制器固定为单元,因此,如果将这些变量分配给特定的HTTP请求,则开发人员将无法创建类级变量。一方面,此功能使您可以将应用程序的性能提高几%,但另一方面,如果控制器中的开发人员为A创建变量特定的HTTP请求。
此外,如果具有默认范围的控制器对请求搜索服务有依赖性,则此类控制器会自动(无警告)也将被请求访问。这样,开发人员根本不能完全依靠控制器中的变量,因为不清楚控制器的范围因此。还有一件事:如果服务是瞬态分析的,那么控制器将不会发生类似的范围更改,这将引入Nestjs Architecture。
在Nestjs v9.0中,有可能创建所谓的durable providers,以便拥有请求的服务,同时又不为每个请求重新创建依赖关系树。从我的测试来看,此类服务的工作速度几乎与常规请求分配服务一样慢,但是添加了Nestjs应用程序体系结构的另一个复杂性。
Dittsmod中控制器的功能
在DitsMod中,每次为每个HTTP请求创建一个控制器实例。无论如何,使用此控制器的性能与Nestjs + fastify的默认范围相同。在任何情况下,控制器或服务的范围都不会自动更改,因此,如果应用程序级别的服务请求请求索取服务,DitsMod会发现未找到请求策略的服务(层次结构中的喷油器更高,看不到它的孩子注射器)。
结论
如果您喜欢Nestjs,很可能会更喜欢Ditsmod。