I have a Rxjs Polling effect like so :
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}),
])
)
)
);
How can I dispatch updateFoo
and updateBar
only when data.foo
or data.bar
change respectively?
I can improve this by using distinctUntilChanged
, doing so the actions wont trigger if data.stuff
changes, however, both actions still dispatch when either one changes.
...
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}),
])
I want to dispatch updateFoo
when data.foo
changes and updateBar
when data.bar
changes, knowing that data
has a lot of other properties that can change as time goes on.
I think this could be an approach:
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})),
),
)
)
)
)
);
The source
from multicast
's second argument is the instance of the Subject which has been declared as the first argument. By using multicast
, we can divide the problem into 2 other smaller problems, without redundantly subscribing to the source(that's why a Subject has been used).