Угловая смесь rxjs наблюдаемая и обещания - PullRequest
0 голосов
/ 04 января 2019

Я занимаюсь разработкой приложения Angular и использую Rxjs, Observables и все, что нужно для передачи данных из моего уровня доступа к данным в компоненты.

У меня есть служба, которая получает данные начальной загрузки (с именем B). Другая служба (с именем A) извлекает эти данные и передает их компоненту через субъект.

Моя цель - сохранить эти данные в моей службе А, но только тогда, когда я получу данные в первый раз. Итак, я буду использовать обещание.

Мне нужно, чтобы мое Обещание «подписалось» на Субъект, а затем напрямую «отписалось».

Я пробовал BehaviorSubject, A ReplaySubject, но Обещание никогда не вызывали ...

Служба начальной загрузки

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 голосов
/ 04 января 2019

Я бы предложил продолжать использовать Observables. Существует оператор канала share , который делится результатами наблюдаемого с каждым, подписавшимся на это наблюдаемое. Вызов осуществляется только один раз.

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
    );
  }
}
...