Dependency Injection

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.

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.

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.

This is the reason, why Nest has its own DI system.

Custom components

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.

Use value:

const  value = {};
@Module({
    controllers: [ UsersController ],
    components: [ 
        { provide: UsersService, useValue: value }
    ],
})

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).

Use class:

@Component()
class CustomUsersService {}

@Module({
    controllers: [ UsersController ],
    components: [
        { provide: UsersService, useClass: CustomUsersService }
    ],
})

When:

  • you want to use chosen, more specific class only in this module.

Use factory:

@Module({
    controllers: [ UsersController ],
    components: [
        ChatService,
        { 
            provide: UsersService, 
            useFactory: (chatService) => {
                return Observable.of('customValue');
            },
            inject: [ ChatService ]
        }
    ],
})

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.

Remember:

  • 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.

Custom providers

@Module({
    controllers: [ UsersController ],
    components: [
        { provide: 'isProductionMode', useValue: false }
    ],
})

When:

  • you want to provide component with a chosen key.

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:

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

@Component()
class SampleComponent {
    constructor(@Inject('isProductionMode') isProductionMode: boolean) {
        console.log(isProductionMode);
    }
}

results matching ""

    No results matching ""