Angular Injector usage
import { Injectable, Injector, Inject } from '@angular/core';
...
@Injectable()
export class DefaultInterceptor implements HttpInterceptor {
constructor(
private injector: Injector,
...
@Injectable()
export class DefaultInterceptor implements HttpInterceptor {
constructor(
private injector: Injector,
@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService
) { }
get msg(): NzMessageService {
return this.injector.get(NzMessageService);
}
private goTo(url: string) {
setTimeout(() => this.injector.get(Router).navigateByUrl(url));
}
private checkStatus(ev: any) {
if (ev.status >= 200 && ev.status < 300) return;
const errortext = CODEMESSAGE[ev.status] || ev.statusText;
this.injector.get(NzNotificationService).error(
`请求错误 ${ev.status}: ${ev.url}`,
errortext
);
}
...
Angular 中注入器是有层级结构的,即创建完注入器,我们可以基于它创建它的子注入器。
- resolveAndCreate() – 根据设置的 provider 数组创建注入器
- resolveAndCreateChild() – 调用已有注入器对象上的该方法,创建子注入器
当调用注入器 get()
方法,获取 token 对应的对象时,默认的查找方式是,优先从本级注入级获取,如果未找到,则往上一级查找,直到根级注入器。若未找到对应的依赖对象,默认会抛出异常。
使用示例
class ParentProvider {}
class ChildProvider {}
var parent = ReflectiveInjector.resolveAndCreate([ParentProvider]);
var child = parent.resolveAndCreateChild([ChildProvider]);
expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true);
expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true);
expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider));
通过分析源码,我们也发现如果两个服务提供商 (Provider) 使用同一个 Token,却没有声明为 multiprovider,那么后面的会把前面的覆盖掉。此外需要注意的是,multiprovider 不能与普通的 provider 混用。
@Self()、@SkipSelf()、@Optional() 等装饰器有什么作用?
- @Self() – 表示只在本级注入器查找依赖对象
- @SkipSelf() – 表示不从本级注入器获取依赖对象
- @Optional – 表示该依赖对象是可选的,如果找不到返回 null