Angular rxjs混合了observable和promise

时间:2019-01-04 14:31:07

标签: angular promise rxjs subscription

我正在开发Angular应用程序,并且使用Rxjs,Observables和所有东西将数据从我的数据访问层传输到组件。

我有一个服务,该服务获取引导数据(名为B)。 另一个服务(名为A)将获取这些数据,并通过主题将它们提供给组件。

我的目标是将这些数据保留在服务A中,但仅当我第一次获取数据时才保留。因此,我将使用Promise。

我需要我的承诺来“订阅”主题,然后直接“取消订阅”。

我尝试了一个BehaviorSubject,一个ReplaySubject,但是Promise从未被调用...

引导服务

export class BService {
  propsFetched: Subject<BootstrapProperties> = new Subject<BootstrapProperties>();

  constructor(private httpClient: HttpClient) { //... }

  init() {
    this.fetchBootstrapProperties().then(
      (res) => {
        // ...
        this.propsFetched.next({ ...res });
      }
    );
  }

  private fetchBootstrapProperties(): Promise<BootstrapProperties> {
    const url = UrlResolver.resolveUrl(UrlResolver.EndPoint.BOOTSTRAP);
    return this.httpClient.get<BootstrapProperties>(url).toPromise();
  }

  getDefaultData(): Observable<Data> {
    return this.propsFetched.pipe(map(data => {
      // Some data computation
      return data;
    }));
  }
}

获取数据并将其传输到组件的服务

export class AService {
  sub$ = new BehaviorSubject<Data>();

  constructor(private bService: BService) {
    // This one works, it's used by my component.
    this.sub$ = this.bService.getDefaultData() as BehaviorSubject<Data>;

    // Now, I want to "keep a copy" of these data, ... But my promise never fires.
    this.sub$.toPromise().then(d => console.log(d));
}

模块和引导配置

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    // ...
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: init,
      deps: [BService],
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

export function init(bService: BService) {
  return () => bService.init();
}

1 个答案:

答案 0 :(得分:0)

我建议继续使用Observables。有一个管道运算符share与所有订阅此Observable的人共享该Observable的结果。呼叫仅进行一次。

export class BService {
  public fetchBootstrapProperties$: Observable<BootstrapProperties>;

  constructor() {
    this.fetchBootstrapProperties$ = this.httpClient.get<BootstrapProperties>(url).pipe(
      map(data => {
        // computation
        // return data
      }),
      share()
    );
  }
}

export class AService {
  constructor(bService: BService) {
    this.bService.fetchBootstrapProperties$.subscribe(data => {
      // get your data
    );
  }
}