My Angular 5 application is based on NgRx, a state management library similar to Redux but based on RxJS.
I often need to get the latest value from the store based on the payload of the current action.
In RxJS terminology, it means that I have my main stream that constantly produce items and for each new item I need to create a side stream based on the item's value, get the latest value from this stream, and combine it with the main stream.
At the moment, I do something like this:
@Effect()
public moveCursor$: Observable<Action> = this.actions$.pipe(
ofType<TableAction.MoveCursor>(TableActionType.MOVE_CURSOR),
switchMap(action => this.store$.select(selectTableById(action.payload.cursor.tableId)).pipe(
first(),
map(table => ({action, table}))
)),
map(({action, table}) => {
...
})
)
I know it is probably not the best solution and I am looking for something like this (which is not possible with withLatestFrom
operator):
@Effect()
public moveCursor$: Observable<Action> = this.actions$.pipe(
ofType<TableAction.MoveCursor>(TableActionType.MOVE_CURSOR),
withLatestFrom(action => this.store$.select(selectTableById(action.payload.cursor.tableId))),
map(([action, table]) => {
...
})
)
So my question is: Is there any RxJS operator which is similar to withLatestFrom
which can take a value produced by the first stream as a parameter?
Deprecations & Breaking Changes RxJS is mostly useful for its operators, even though the Observable is the foundation. Operators are the essential pieces that allow complex asynchronous code to be easily composed in a declarative manner. Operators are functions. There are two kinds of operators:
Just as many array libraries combine map () and flat () (or flatten ()) into a single flatMap (), there are mapping equivalents of all the RxJS flattening operators concatMap (), mergeMap (), switchMap (), and exhaustMap (). To explain how operators work, textual descriptions are often not enough.
While the similar combineLatest operator emits a new value whenever there’s a new emission from any of the input streams, withLatestFrom emits a new value only if there’s a new emission from the guiding stream.
Other useful flattening operators (called join operators) are mergeAll () — subscribes to each inner Observable as it arrives, then emits each value as it arrives
I finally did it...
doEffect$ = this.actions$.pipe(
ofType<someAction>(losActionTypes.someAction),
switchMap/mergeMap/concatMap( // according to your logic
action => of(action).pipe(
withLatestFrom(this.store.pipe(select(leFancySelector)))
)),
tap(console.log) // tap if you don't believe me
You can use mergeMap
and map
to combine the action with the table selected from the store:
@Effect()
public moveCursor$: Observable<Action> = this.actions$.pipe(
ofType<TableAction.MoveCursor>(TableActionType.MOVE_CURSOR),
mergeMap(action => this.store$
.select(selectTableById(action.payload.cursor.tableId))
.pipe(
first(),
map(table => [action, table])
)
),
map(([action, table]) => {
...
})
)
And you'd need to use first
- or take(1)
- to ensure that the inner observable selected from the store emits only a single value - the table that's to be combined with the action.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With