Angular Injector usage

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

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.