Providers and Tokens
The building blocks of DI are Provider(s) and InjectionToken(s).
InjectionToken
- asymbol
orclass
representing an object or any value in Dependency Injection space.Provider
- provides a value to a specific token.
#
Defining TokensDependency Injection is an abstraction over actual objects and values.
There are three kinds of providers:
- Class provider - creates an instance of a class
- Value provider - provides ready-to-use value
- Factory provider - function to provide a value
#
ClassUsing a class
provider in GraphQL Modules is the easiest approach to DI. The class is instantiated automatically and in case of Operation Scope it's created only on demand.
Every Service should be decorated with @Injectable
as follows:
It's a shorthand expression for:
- Expression
- Example
#
ValueValue provider requires a Token that represents a value, either InjectionToken
or a class.
- Expression
- Example
#
FactoryIn case you want to create a dependent value, using a factory provider is the answer. Factory can be useful also to create an instance of a class, for example when using third-party libraries.
- Expression
- Example
#
Using Services and TokensProvider is a way to define a value and match it with a Token or a Service. Let's see how to consume Services and Tokens.
#
ServiceAccessing a service is fairly simple. You ask for a service in a constructor of a class or by using Injector
directly.
- Resolver
- Service
Injector
is available in GraphQL Context underinjector
property.
#
InjectionTokenConsuming InjectionToken
is very similar to Service
. The only difference is that you need to use @Inject
decorator but only in some cases.
- Resolver
- Service
Injector
is available in GraphQL Context underinjector
property.
@Inject
decorator is needed because of limitation of type system.
#
Global Providers and TokenModule is able to share tokens and providers with other modules, even application. When enabling a global flag, the provider still depends on an original Injector.
- Definition
- Usage
In the scenario above, we've got two modules: Posts and Users.
Both modules defines their own Logger
.
Users module defines Auth
service as globally available.
Posts module defines Posts
service.
When Posts.getMyPosts()
is called, it fetches a current user from Auth
service.
The Auth.getCurrentUser()
calls a logger (provided by Users
module).
In Posts.getMyPosts()
a different logger is invoked (provided by Posts
module).
What all of that mean? Because global providers are accessible in all modules, they still use the injector they were created by. Global providers are still isolated but their API is public to other modules.
#
Lazy with forwardRefThe forwardRef
function allows to refer to references which are not yet defined. Useful when circular dependency of modules is an issue.
#
Available TokensGraphQL Modules have a set of built-in and ready to use Tokens. They may be handy in some situations.