Angular Providers - quan1997ap/angular-app-note GitHub Wiki
https://www.tektutorialshub.com/angular/angular-providers/
The Angular Provider is an instruction (or recipe) that describes how an object for a certain token is created. The Angular Providers is an array of such instructions (Provider). Each provider is uniquely identified by a token (or DI Token ) in the Providers Array.
Register the services in the Providers metadata. There are two way
- Register directly in the Providers array of the @NgModule or @Component or in @Directive.
- Or use the providedIn property of the @Injectable decorator.
Bước 1: The Angular Components or Angular Services declare the dependencies they need in their constructor.
Bước 2: The Injector reads the dependencies and looks for the provider in the providers array using the Token.
Bước 3: It then instantiates the dependency using the instructions provided by the provider. The Injector then injects the instance of the dependency into the Components/Services.
To Provide an instance of the dependency, we need to register it in the Providers metadata Có 2 cách để đăng kí dependence ( 2 cách tương tự nhau)
Cách 1: providers: [ProductService]
Cách 2: providers :[{ provide: ProductService, useClass: ProductService }]
The Providers are registered using the token. The tokens are used to locate the provider.
Types of the token: Type, String, Injection Token
-
Type
- Inject the instance of the ProductService => use the ProducService as the token
// module.ts
providers :[{ provide: ProductService, useClass: ProductService }]
// component.ts
class ProductComponent {
constructor(
private productService : ProductService
) {}
- String
// module.ts
{provide:'PRODUCT_SERVICE', useClass: ProductService },
{provide:'USE_FAKE', useValue: true },
{provide:'APIURL', useValue: 'http://SomeEndPoint.com/api' },
// component.ts
class ProductComponent {
constructor(
@Inject('PRODUCTSERVICE') private prdService:ProductService,
@Inject('APIURL') private apiURL:string ) { }
}
- Injection Token: Tạo token động
// module.ts
export const API_URL= new InjectionToken<string>('');
providers: [
{ provide: API_URL, useValue: 'http://SomeEndPoint.com/api' }
]
// component.ts
constructor(@Inject(API_URL) private apiURL: string) {
}
The Provider also tells the Angular Injector how to create the instance of dependency.
- useClass - this option tells Angular DI to instantiate a provided class when a dependency is injected + Use the Class Provider useClass, when you want to provide an instance of the provided class. + Vd: Test Service/ mock service . Chuyển giữa service thật và service mock có cùng các function giống nhau
Bước 1: Tạo service và test service
// Real Service
export class ProductService {
getData() {
return 'real data';
}
}
// Mock service
export class FakeProductService{
getData() {
return 'mock data';
}
}
Bước 2: Inject dependency
providers :[{ provide: ProductService, useClass: ProductService }] or providers: [ProductService]
Bước 3: Switching Dependencies - Chuyển qua lại giữa 2 service để thuận tiện cho việc test
providers :[{ provide: ProductService, useClass: FakeProductService }]
Bước 4:
// ... import bookService
this.bookService.getMockData();
Kết quả :
- useClass service nào thì nhận kết quả hàm getMockData() tương ứng của service đó.
- Angular DI to instantiate a provided class when a dependency is injected
Kết quả: Nếu ``useClass: fakeProductService``` thì trong component sử
- useExisting - allows you to alias a token and reference any existing one.
-
useFactory - allows you to define a function that constructs a dependency.
- We usually use the useFactory when we want to return an object based on a certain condition.
- Use case
Khi muốn inject 1 service ( ProductService / FakeProductService ) dựa trên giá trị USE_FAKE.
ProductService cần sử dụng dependence LoggerService. Thì thêm các thành phần đó vào mảng deps => (deps: ['USE_FAKE', LoggerService])
providers: [
{ provide: LoggerService, useClass: LoggerService },
{ provide: 'USE_FAKE', useValue: true },
{
provide: ProductService,
useFactory: (USE_FAKE, LoggerService) =>
USE_FAKE ? new FakeProductService() : new ProductService(LoggerService),
deps: ['USE_FAKE', LoggerService]
}
]
- useValue - provides a static value that should be used as a dependency.
const APP_CONFIG = Object.freeze({
serviceURL: 'www.serviceUrl.comapi',
IsDevleomentMode: true
});
providers: [
{ provide: 'APP_CONFIG', useValue: APP_CONFIG }
]
export class AppComponent {
constructor(
@Inject('APP_CONFIG') public appConfig: any
) {}
}