Angular 4服务:如何实现异步init进程?

时间:2017-10-20 16:01:25

标签: angular typescript asynchronous

我正在构建一个Angular 4服务,该服务提供对某些数据的访问。当这项服务是第一次 实例化后,它需要建立与数据存储的连接,这是一个异步过程。

如何在此异步连接过程完成之前,最好地阻止此服务的用户(,组件或其他服务)尝试使用该服务?

我的服务是否有某种方式可以告诉Angular的引导程序在继续之前等待此承诺解决?

如果重要,该服务已在我providers的{​​{1}}数组中注册。所以(据我所知),Angular将构建一个服务实例,该实例将提供给注入@NgModule的任何组件或其他服务。

明确地说,这是我害怕的情景:

  1. 在应用程序引导过程中,Angular会在模块的MyService数组中看到MyService,并调用其构造函数。

  2. providers的构造函数开始连接过程,可能需要一两秒钟。

  3. 与此同时,Angular的引导程序继续向前充电,并呈现我的应用程序的仪表板。

  4. 仪表板组件注入MyService,并且(在其自己的构造函数中,或者可能在MyService中)尝试在建立连接之前调用ngOnInit

  5. 为了说明这里的服务:

    myService.getData()

1 个答案:

答案 0 :(得分:1)

您需要做的是延迟应用初始化,直到建立连接。您可以使用下面的APP_INITIALIZER令牌来执行此操作,

完成Plunker!!

onAppInit Factory返回初始化承诺

export function onAppInit(svc: MyService): () => Promise<any> {
  return svc.initialize;
}

AppModule

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  providers: [
    MyService,
    {
      provide: APP_INITIALIZER,
      useFactory: onAppInit,
      deps: [MyService],
      multi: true
    }
  ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

<强>为MyService

@Injectable()
export class MyService{
  connection;

  constructor(){}

  initialize = (): Promise<any> => {
     return new Promise( (resolve, reject) =>  { 
         setTimeout(() => { 
          this.connection = {
             data : {
               "var1": "xyz" 
             }
          };
          resolve();
         }, 3000);
     });
  }

  getData = () => {
    console.log(this.connection);
    return this.connection.data;
  }
}

AppComponent

@Component({
  selector: 'my-app',
  template: `<h1>Hello</h1>
  <hr />
  {{data | json}}
  `
})
export class AppComponent { 
  data;
  constructor(private svc: MyService){ }

  ngOnInit(){
    this.data = this.svc.getData();
  }
}

这可以解决您在问题中的问题,但请注意,在初始化服务之前,您的应用程序不会呈现,这可能是糟糕的用户体验,具体取决于可接受的延迟数

更好的解决方案是从@JBNizet评论中建议的getData()返回promise或Observable。

希望这会有所帮助!!