首页 > 解决方案 > 使用 rxjs 的角度加载服务

问题描述

我的 Angular 应用程序包含一些服务,这些服务需要在显示应用程序组件之前初始化数据异步(pe 从 API 和 i18n 通过 ng-translate 加载初始数据)。在中央服务中,我想观察所有异步任务并提供一个 Observable 来通知其他组件和服务系统已准备好(并隐藏加载动画)。

我的第一个尝试是:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { combineLatest } from 'rxjs/observable/combineLatest';

@Injectable({
  providedIn: 'root',
})
export class LoadingService {

  private tokens: Observable<boolean>[] = [];
  public tokenObservable: Observable<boolean[]>;

  constructor() {
    this.tokenObservable = combineLatest(this.tokens);
  }

  public registerLoadingToken(token: Observable<boolean>): void {
    this.tokens.push(token);
  }
}

所有初始化服务都必须在这个 LoadingService 中注册一个 Observable。但我认为我遇到了时间问题。该计划是:

但是我怎样才能正确设置时间呢?

如果我在构造函数中使用 combineLatest,则不会注册任何令牌。

如果我使用 combineLatest 异步(如:)setTimeout({}, 0),则可观察到的公共令牌为空。

你对我有什么想法吗?

标签: angularrxjsloading

解决方案


好的:这有效:

加载服务:

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { combineLatest } from 'rxjs/observable/combineLatest';

@Injectable({
  providedIn: 'root',
})
export class LoadingService {

  private tokens: Observable<any>[] = [];
  private internalSubject = new Subject<any>();
  public tokenObservable: Observable<any>;

  constructor() {
    this.tokenObservable = this.internalSubject.asObservable();
  }

  // call in the OnInit of app.component.ts
  public listenToTokens(): void {
    combineLatest(this.tokens).subscribe(_ => this.internalSubject.next(true));
  }

  public registerLoadingToken(token: Observable<any>): void {
    this.tokens.push(token);
  }
}

我的异步服务:

public awaiter: Subject<any>;

  constructor(
    apiService: ApiService,
    private navigationService: NavigationService,
    private translationService: TranslateService,
    loadingService: LoadingService) {
    loadingService.registerLoadingToken(this.awaiter);
    apiService.get<api.Field[]>('FormMetadata').subscribe(_ => {
      this.setMetadata(_);
      this.awaiter.next(true);
    }, _ => this.handleError(_));
  }

和 appComponent.ts:

  ngOnInit(): void {
    this.loadingService.listenToTokens();
  }

然后我可以在我的 MainComponent 上订阅它:

  constructor(loadingService: LoadingService) {
    loadingService.tokenObservable.subscribe(_ => this.state = 'none');
  }

推荐阅读