Study Directory
- Angular 4 Dependency Injection Tutorial One Introduction to Dependency Injection
- Angular 4 Dependency Injection Tutorial Two Component Service Injection
- Angular 4 Dependency Injection Tutorial Three Use of ClassProvider
- Angular 4 Dependency Injection Tutorial 4 The use of FactoryProvider
- Angular 4 Dependency Injection Tutorial 5 FactoryProvider configures dependency objects
- Angular 4 Dependency Injection Tutorial Six Injectable Decorator
- Angular 4 Dependency Injection Tutorial 7 Use of ValueProvider
- Angular 4 Dependency Injection Tutorial 8: Usage of InjectToken
Preface
This article belongs to the fourth chapter of the Angular 4 Dependency Injection Learning Series, which mainly introduces the use of FactoryProvider for Angular 4 Dependency Injection. Interested friends will take a look at the detailed introduction below:
The development environment and development language of this series of tutorials:
- Angular 4 +
- Angular CLI
- TypeScript
Basic knowledge
The role of FactoryProvider
FactoryProvider is used to tell the Injector (injector) to return the dependency object corresponding to the Token by calling the function corresponding to the useFactory.
Use of FactoryProvider
function serviceFactory() { return new Service(); } const provider: FactoryProvider = { provide: 'someToken', useFactory: serviceFactory, deps: [] };
FactoryProvider interface
export interface FactoryProvider { // Used to set the token value associated with the dependent object. The token value may be Type, InjectionToken, // instance or string of OpaqueToken provide: any; // Set the factory function used to create objects useFactory: Function; // Dependency object list deps?: any[]; // Used to identify whether multiple providers. If it is a multiple type, it returns the dependency associated with the token. // Object list multi?: boolean; }
FactoryProvider
After introducing the basics, we will get to the topic immediately. I don’t know if you still remember the HeroComponent component we created before:
import { Component, OnInit } from '@angular/core'; import { HeroService } from '../'; @Component({ selector: 'app-hero', template: ` <ul> <li *ngFor="let hero of heros"> ID: {{}} - Name: {{}} </li> </ul> ` }) export class HeroComponent implements OnInit { constructor(private heroService: HeroService) { } heros: Array<{ id: number; name: string }>; ngOnInit() { = (); } }
So now the question is, what should we do if we want to output debugging information when obtaining hero data? What ~, isn't this problem very simple? Use it directly API
Isn't it enough to output the corresponding information:
('Fetching heros...'); = ();
The problem comes again. If multiple components use HeroService to obtain hero data, then does each component have to add the corresponding statement? In addition, if you want to modify the output debugging information, you have to modify multiple places in the program. In fact, we usually only need to output debugging information in the development stage, so the above solution is unreasonable and not flexible enough.
In fact, we can learn from the previous idea of introducing HeroService services and create a LoggerService to solve the problems mentioned above.
Create a LoggerService service
export class LoggerService { constructor(private enable: boolean) { } log(message: string) { if() { (`LoggerService: ${message}`); } } }
Configure LoggerService Service
@NgModule({ ... providers: [ HeroService, LoggerService ], bootstrap: [AppComponent] }) export class AppModule { }
Use LoggerService Service
import { Component, OnInit } from '@angular/core'; import { HeroService } from '../'; import { LoggerService } from './../'; @Component({ selector: 'app-hero', template: ` <ul> <li *ngFor="let hero of heros"> ID: {{}} - Name: {{}} </li> </ul> ` }) export class HeroComponent implements OnInit { heros: Array<{ id: number; name: string }>; constructor(private heroService: HeroService, private loggerService: LoggerService) { } ngOnInit() { ('Fetching heros...'); = (); } }
After the above code is run, the following exception information will be thrown:
Uncaught Error: Can't resolve all parameters for LoggerService: (?).
Some readers' eyes lit up, maybe you forgot to use the @Injectable decorator when you created the LoggerService service. Haha, I actually did it on purpose, but I added@Injectable()
After that, the following exception was thrown:
ERROR Error: No provider for Boolean!
Why does the above exception information appear? Let's take a look at the LoggerService service created earlier:
export class LoggerService { constructor(private enable: boolean) { } // ... }
In Angular we inject dependent objects through construct injection.private enable: boolean
This way means that we want to inject an object of type Type. Then boolean represents the basic data type, not the required Type type:
export function isType(v: any): v is Type<any> { return typeof v === 'function'; }
Next, let's take a look at the earliest thrown exception:
Uncaught Error: Can't resolve all parameters for LoggerService: (?).
In fact, the answer to the problem is also in the constructor of the LoggerService class. When creating a LoggerService object, we need to set the value of the enable parameter. So how to solve it? Of course we can use our protagonist - FactoryProvider.
The details are as follows:
Using FactoryProvider
@NgModule({ ..., providers: [ HeroService, { provide: LoggerService, useFactory: () => { return new LoggerService(true); } } ], bootstrap: [AppComponent] }) export class AppModule { }
When you update the code, then have a gorgeous save operation, and finally open your console and you will see the expected output information:
LoggerService: Fetching heros...
Is that the end? The relevant content about FactoryProvider has come to an end first. In the next article, we will introduce how to use FactoryProvider to configure dependencies.
Summarize
The above is the entire content of this article. I hope that the content of this article will be of some help to everyone’s learning or using Angular 4. If you have any questions, you can leave a message to communicate. Thank you for your support.