Skip to content

什么是异步初始化服务

前面有介绍什么是服务,服务是指包含数据和方法的对象。

关键在于怎么初始化服务的数据。一般来说简单的服务就是代码在定义服务时就写死的默认数据。此时不会涉及到异步初始化服务。

当我们初始化服务的数据需要从服务器端获取时,就需要通过接口异步获取数据后才能完成数据的初始化。

示例 1

ts
class A {
  public id = 1;
  public name = 'A';
}

这里的 A 是一个服务,而且可以明确看出来这个服务是不依赖服务器端数据的,所以不需要异步初始化数据。

示例 2

ts
class A {
  public id = 1;
  public name = 'A';

  @PostConstruct()
  public init() {
    return fetch('api_url').then(res => {
      this.id = res.id;
      this.name = res.name;
    });
  }
}

这里通过@PostConstruct装饰了一个 init 方法。这个 init 方法会在服务实例化之后自动执行,这样就能自动通过接口从服务器端拉取数据,从而完成服务数据的初始化。

示例 3

ts
class B {
  public id = 2;
  public name = 'B';

  @PostConstruct()
  public init() {
    return fetch('api_url').then(res => {
      this.id = res.id;
      this.name = res.name;
    });
  }
}

class A {
  public id = 1;
  public name = 'A';

  @Inject(B)
  public b: B;

  @PostConstruct(true)
  public init() {
    this.id = this.b.id + 1;
    this.name = this.b.name + 'A';
  }
}

这个例子稍微有些复杂。其中 B 服务依赖后端接口返回的数据用户初始化服务。同时 A 服务的 init 方法又是依赖 B 服务的 id 和 name 属性的。 这里显然需要控制代码的执行顺序。如果两个 init 方法同时执行,则 A.init 执行时,B 服务还没有获取到服务器端数据,此时 A 服务访问的就是 B 服务的默认数据,显然这不是我们期望的逻辑。 所以这里使用了@PostConstruct(true),这里的true用于控制等待 A 的所有注入的属性全部完成初始化之后再去执行 A 服务自己的 init 方法。这样 A.init 方法中就能访问到真实的 B 服务的数据了。

示例 4

ts
class C {
  public id = 3;
  public name = 'C';

  @PostConstruct()
  public init() {
    return fetch('api_url_C').then(res => {
      this.id = res.id;
      this.name = res.name;
    });
  }
}

class B {
  public id = 2;
  public name = 'B';

  @PostConstruct()
  public init() {
    return fetch('api_url_B').then(res => {
      this.id = res.id;
      this.name = res.name;
    });
  }
}

class A {
  public id = 1;
  public name = 'A';

  @Inject(B)
  public b: B;

  @Inject(C)
  public c: C;

  @PostConstruct(true)
  public init() {
    this.id = this.b.id + this.c.id + 1;
    this.name = this.b.name + this.c.name + 'A';
  }
}

这个例子展示了 A 服务同时依赖 B 和 C 两个服务,此时 A 服务也会等待 B 服务和 C 服务都完成初始化之后,才会执行 A.init 方法。

示例 5

ts
class C {
  public id = 3;
  public name = 'C';

  @PostConstruct()
  public init() {
    return fetch('api_url_C').then(res => {
      this.id = res.id;
      this.name = res.name;
    });
  }
}

class B {
  public id = 2;
  public name = 'B';

  @Inject(C)
  public c: C;

  @PostConstruct(true)
  public init() {
    this.id = this.c.id + 2;
    this.name = this.c.name + 'B';
  }
}

class A {
  public id = 1;
  public name = 'A';

  @Inject(B)
  public b: B;

  @PostConstruct(true)
  public init() {
    this.id = this.b.id + 1;
    this.name = this.b.name + 'A';
  }
}

这个例子展示了 A 服务依赖 B 服务,B 服务又是依赖 C 服务。首先 B 服务会等待 C 服务完成初始化,才会执行 B.init 方法。等到 B 服务完成初始化,才会执行 A.init 方法,最终完成 A 服务的初始化。

参考资料