首页 > 解决方案 > 仅当 Rxjs 轮询上的某些属性更改时才调度 NgRx 操作

问题描述

我有一个像这样的 Rxjs 轮询效果:

updateProductData$ = createEffect(() =>
  this.actions$.pipe(
    ofType(fromActions.loadProduct),
    switchMap(_) =>
      this.http.get('endpoint').pipe(
        delay(1000),
        repeat(),
        switchMap((data) => [
          fromActions.updateFoo({foo: data.foo}),
          fromActions.updateBar({bar: data.bar}),
        ])
      )
    )
  );

我怎样才能分别发送updateFooupdateBar仅在何时发送data.foodata.bar更改?

我可以通过使用来改进这一点distinctUntilChanged,这样做不会在更改时触发操作data.stuff,但是,当任一操作发生更改时,这两个操作仍会分派。

...
     repeat(),
     distinctUntileChanged((prev, curr) => prev.foo === curr.foo && prev.bar === curr.bar) // works but it fires both actions when either one changes
     switchMap((data) => [
       fromActions.updateFoo({foo: data.foo}),
       fromActions.updateBar({bar: data.bar}),
     ])

我想在更改和更改时进行调度,因为updateFoo我知道它还有很多其他属性会随着时间的推移而改变。data.fooupdateBardata.bardata

标签: angularrxjsngrx

解决方案


我认为这可能是一种方法:

updateProductData$ = createEffect(() =>
  this.actions$.pipe(
    ofType(fromActions.loadProduct),
    switchMap(_) =>
      this.http.get('endpoint').pipe(
        delay(1000),
        repeat(),
        
        multicast(
          new Subject(),
          source => merge(
            // concerning `foo`
            source.pipe(
              distinctUntilChanged((prev, crt) => prev.foo === crt.foo),
              map(data => fromActions.updateFoo({foo: data.foo})),
            ),

            // concerning `bar`
            source.pipe(
              distinctUntilChanged((prev, crt) => prev.bar === crt.bar),
              map(data => fromActions.updateBar({bar: data.bar})),
            ),
          )
        )
      )
    )
  );

sourcefrom的multicast第二个参数是已被声明为第一个参数的 Subject 的实例。通过使用multicast,我们可以将问题分成 2 个其他较小的问题,而无需冗余订阅源(这就是使用主题的原因)。


推荐阅读