简体   繁体   中英

nestjs modules - whats the diffrence beetwean providers and imports

Im following the nestJs authentication tutorial

In auth/auth.module.ts:

import { JwtModule } from '@nestjs/jwt'


...

@Module({
  imports: [

    UsersModule,
    PassportModule,
    JwtModule.register({
      secret: jwtConstants.secret,
      signOptions: { expiresIn: '60s' },
    }),
  ],
  providers: [AuthService, LocalStrategy, JwtStrategy],
  exports: [AuthService],
})

So JwtModule is imported under 'imports'.

In the auth/auth.service.ts the JwtService is being injected

...
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(
    private usersService: UsersService,
    private jwtService: JwtService
  ) {}

...

From the nestJs docs:

Under Module: providers - the providers that will be instantiated by the Nest injector and that may be shared at least across this module

imports -   the list of imported modules that export the providers which are required in this module

Under Providers:

Providers are a fundamental concept in Nest.
Many of the basic Nest classes may be treated as a provider – services, repositories, 
factories, helpers, and so on. 
The main idea of a provider is that it can be injected as a dependency; 
this means objects can create various relationships with each other, and the function 
of "wiring up" instances of objects can largely be delegated to the Nest runtime system

I don't really understand. Whats the difference between providers and imports if both are used for dependency injection?

Think of a provider as a single thing that can be injected and used. It can be a full class, like an AuthService , or an object like { secretOrKey: 'sup3rs3cr3t' } or even just a number like 42 . Each of these objects would be represented by a provider token: for classes, this is just the class reference itself which will later be read via the emitted metadata, the object and number would be represented by an injection token specified by a custom provider like

{
  provide: 'JWT_OPTIONS',
  useValue: {
    secretOrKey: 'sup3rs3cr3t',
  }
}

or

{
  provide: 'THE_ANSWER',
  useValue: 42,
}

To inject these custom providers, by the way, you'd end up using @Inject('JWT_OPTIONS') or @Inject('THE_ANSWER') in the constructor of another service or just the injection tokens in an inject array for a factory custom provider


Modules, on the other hand, are a collection of modules, providers, controllers, and exports, that tie a feature together. Almost think of it like a container, it has its own private API (providers that aren't exports) (these are providers and methods that are used from within the module but not outside of it), a public API (exported providers) (these are providers and imported modules that are used both inside and outside of the module) and external entry points (controllers, resolvers, gateways) (these are ways that transports can talk to your application and specifically your module).

What a module declares under its providers array, Nest will create that provider in the context of the module: this goes for providers that are instantiated in other modules, providers that are just objects, etc, they'll be created with whatever resources the module has.

Most of the time, if you declare a provider in two providers arrays you're going to have side effects that you don't expect to have. What you usually want to do instead is to have a single module declare the provider and add it to its exports array, then in another module import the first to get access to those exports ; this will have Nest re-use the existing provider in the new module to allow usage of the provider without needing to recreate it.


On to your example of the JwtModule , if we take a look at the source module we'll see that there is one provider that is always present, the JwtService , and it is also always exported, and there is one provider that shows up when you use register/registerAsync , the JWT_MODULE_OPTIONS provider. This provider is never exported, so it's only existing inside of the module. However, when we import the JwtModule , whatever module we import the JwtModule into now can inject the JwtService into its providers due to the JwtModule having the JwtService in the exports . If a provider were to try to inject JWT_MODULE_OPTIONS , then there would be an error, as the new module doesn't know about that provider (unless of course you make your own provider for it with the same name)

Hopefully this all helps clear things up

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM