Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an RxJS operator similar to withLatestFrom but with a parameter?

Tags:

angular

rxjs

ngrx

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?

like image 895
livthomas Avatar asked Mar 11 '18 21:03

livthomas


People also ask

What are RxJS operators?

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:

What are the different types of flattening operators in RxJS?

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.

What is the difference between combinelatest and withlatestfrom?

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.

What are the operators for flattening observables?

Other useful flattening operators (called join operators) are mergeAll () — subscribes to each inner Observable as it arrives, then emits each value as it arrives


2 Answers

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
like image 196
Kris Jobs Avatar answered Nov 10 '22 05:11

Kris Jobs


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.

like image 24
cartant Avatar answered Nov 10 '22 05:11

cartant