如何同步两个订阅,以使一个订阅仅在另一个发出时启动

时间:2019-08-07 10:16:25

标签: angular typescript rxjs observable

我正在开发一个有角度的应用程序,我遇到的情况是:一个可观察到的信号,表示已从远程获取了一些数据(dataFetchedEvent$),以及一种使用该远程数据并侦听用户更改的形式({{ 1}})。

formChanges$

使用此代码可以正常工作,但在每次 const dataFetchedEvent$ = this.event.asObservable() .pipe( tap((fetchedData) => { this.createFormControls(fetchedData); // creates the reactive form control based on the data fecthed from remote }), takeUntil(this.componentDestroyed) // fired when in the ngOnDestroy of the component ); const formChanges$ = this.form.valueChanges // listen form changes .pipe( switchMap((formDataRaw) => this.formatData(formDataRaw)), // transform data takeUntil(this.componentDestroyed) ); dataFetchedEvent$.subscribe(); formChanges$.subscribe( (formattedFormData) => { // do stuff... } ); 更改控件时,每次dataFetchedEvent$都会触发formChanges$订阅,因此我想避免这种情况。 我的目标是仅在创建或更新表单控件后才侦听表单更改。 我尝试了多种解决方案,但每种解决方案都有一定的局限性:

使用 skipUntil

this.createFormControls(fetchedData)

此解决方案避免了在创建控件时 const formChanges$ = this.form.valueChanges // listen form changes .pipe( skipUntil(dataFetchedEvent$), switchMap((formDataRaw) => this.formatData(formDataRaw)), // transform data takeUntil(this.componentDestroyed) ); 流的多次发射,并且在销毁组件并重新创建组件时(例如,当用户更改页面并返回时)工作,但是对于skipUntil {{ 1}}在第一次发出后不再订阅,在某些情况下,formChanges$必须再次发出并更新表单控件。

concat

dataFetchedEvent$

在这种情况下,dataFetchedEvent$流从未被订阅,我认为这是因为dataFetchedEvent $未完成。

具有最新组合

   const formChanges$ = this.form.valueChanges // listen form changes
      .pipe(
        switchMap((formDataRaw) => this.formatData(formDataRaw)), // transform data
        tap((formattedFormData) => {
          // do stuff...
        }),
        takeUntil(this.componentDestroyed)
      );

    concat(dataFetchedEvent$, formChanges$).subscribe();

这不是我要查找的,因为在创建控件时仍会发出formChanges $流。

使用 mergeMap或switchMap

formChanges$

这是第一次执行,或者如果销毁并重新创建了该组件,但是如果combineLatest(dataFetchedEvent$, formChanges$).subscribe([val1, val2] => { // do stuff... }); 在第一次更新表单控件后第一次发出const dataFetchedEvent$ = this.event.asObservable() .pipe( tap((fetchedData) => { this.createFormControls(fetchedData); // creates the reactive form control based on the data fecthed from remote }), mergeMap(() => formChanges$), takeUntil(this.componentDestroyed) // fired when in the ngOnDestroy of the component ); dataFetchedEvent$.subscribe(); 之后再次发出。对于dataFetchedEvent$,其行为是相同的。

哪种方法是实现我的目标的最佳方法?

------编辑------

在我的示例中,代码是通用且经过简化的。

这是表单控件

formChanges$

唯一更改的组是类别,当发出switchMap时,意味着新类别已从远程感染,并且我使用form = this.fb.group({ tourLength: this.fb.group({ length: [false] }), types: this.fb.group({ type: [false] }), categories: this.fb.group({}), languages: this.fb.group({ lang: [false] }), prices: this.fb.group({ opt: [false] }) }); (即先前的dataFetchedEvent$

)更新了控件。
_createControlsCategories()

}

每个类别都绑定到视图中的复选框。

1 个答案:

答案 0 :(得分:0)

签出

const dataFetchedEvent$ = this.event.asObservable()
  .pipe(
    tap((fetchedData) => {
      this.createFormControls(fetchedData); 
    }));

  dataFetchedEvent$
    .pipe(
      switchMap(() => formChanges$.pipe(takeUntil(dataFetchedEvent)),
      takeUntil(this.componentDestroyed)
  ).subscribe();
相关问题