依赖注入
Dependency Injection is a strong mechanism, which helps us easily manage dependencies of our classes. It is very popular pattern in strongly typed languages like C# and Java.
依赖注入是一个很强大的机制,该机制可以帮助我们轻松管理各个类的依赖。它在类型非常强大的语言如c#
和Java
中是非常流行的模式。
In Node.js it is not such important to use those kind of features, because we already have amazing module loading system and e.g. sharing instance between files is effortless.
在Node.js中,这些功能不是很重要。因为我们已经有了很强大的模块加载系统。比如说,我们可以很轻易地文件之间分享实例。
The module loading system is sufficient for small and medium size applications. When amount of code grows, it is harder and harder to smoothly organize dependencies between layers. It is also less intuitive than DI by constructor.
对于小中型应用程序来说,模块加载系统已经完全够用了。当代码量增加时,组织各个层之间的依赖会变得越来越困难。它还不如构造函数的DI直观。
This is the reason, why Nest has its own DI system.
所以Nest有一套自己的DI系统。
自定义组件
You have already learnt, that it is incredibly easy to add component to chosen module:
你应该已经了解到向选定模块添加组件是非常简单的:
@Module({
controllers: [ UsersController ],
components: [ UsersService ]
})
But there is some other scenarios, which Nest allows you to take advantages of.
但是Nest允许你使用其他场景。
When:
- you want to use specific value. Now, in this module Nest will associate value with UsersService metatype,
- you want to use test doubles (unit testing).
当
- 你想使用具体的值时。在这个模块中,Nest会将值与
UsersService
元数据相结合。 - 你想使用测试替身时(单元测试)。
使用值:
const value = {};
@Module({
controllers: [ UsersController ],
components: [
{ provide: UsersService, useValue: value }
],
})
When:
you want to use chosen, more specific class only in this module.
当
- 你想仅在此模块箱使用更精确的选定的类时
使用类:
@Component()
class CustomUsersService {}
@Module({
controllers: [ UsersController ],
components: [
{ provide: UsersService, useClass: CustomUsersService }
],
})
When:
- you want to provide a value, which has to be calculated using other components (or custom packages features),
- you want to provide async value (just return Observable or Promise), e.g. database connection.
当
- 你想提供一个必须使用其他组件(或其他自定义包功能)进行计算的值时。
- 你想提供异步值(只返回
Observable
或者Promise
),例如数据库连接。使用 factory:
@Module({
controllers: [ UsersController ],
components: [
ChatService,
{
provide: UsersService,
useFactory: (chatService) => {
return Observable.of('customValue');
},
inject: [ ChatService ]
}
],
})
记住:
- if you want to use components from module, you have to pass them in inject array. Nest will pass instances as a arguments of factory in the same order.
如果你想使用模块内的组件,必须在inject
数组中传递组件。Nest会以相同的顺序传递实例作为factory
的参数。
When:
- you want to provide component with a chosen key.
当
- 你想提供有选定
key
的组件时。
自定义 providers
@Module({
controllers: [ UsersController ],
components: [
{ provide: 'isProductionMode', useValue: false }
],
})
Remember:
记住
- it is possible to use each types useValue, useClass and useFactory. How to use? To inject custom provided component with chosen key, you have to tell Nest about it, just like that:
可以使用每一个类型的useValue
,useClass
和useFactory
.
如何使用呢?注入带有选定key
的自定义提供的组件,并以如下方式告知Nest:
import { Inject } from '@nestjs/common';
@Component()
class SampleComponent {
constructor(@Inject('isProductionMode') isProductionMode: boolean) {
console.log(isProductionMode);
}
}