Rxjs: missing switchMap like operator

Created on 21 Nov 2016  路  4Comments  路  Source: ReactiveX/rxjs

Using @ngrx library there is a very common use-case that can't be done with any of the mapping operators (switchMap, mergeMap, exhaustMap).

Imagine the following effect. (Whenever we want to get something from the server we emit an action, and then make an http call)

@Effect() getAll$: Observable<Action> = this.actions$
    .ofType("GET_ALL")
    .map<string>(x => x.payload)
    .switchMap((group) => this.service.getAll(group)
        .map(response => this.action.getAllSuccess(response))
        .catch((error: Error) => Observable.of(this.action.getAllFail(error)))
    );

If I emit the following actions, only the request that belongs to "group3" will be sent.

this.store.dispatch({ type: "GET_ALL", payload: "group1" })
this.store.dispatch({ type: "GET_ALL", payload: "group2" })
this.store.dispatch({ type: "GET_ALL", payload: "group3" })

If I use mergeMap instead of switchMap, the example above works. However if multiple components emit the action with the same payload, it will send multiple requests.

An operator that behaves like switchMap, but only cancels the inner observable when there is a pending inner observable with that payload (be default using ===, but it could accept a compare function) would be needed to handle these issues.

Most helpful comment

In this case wouldn't groupBy work more or less for what you're trying to accomplish?

@Effect() getAll$: Observable<Action> = this.actions$
    .ofType("GET_ALL")
    .groupBy(x => x.payload)
    .mergeMap((group) => group.switchMap(({payload}) => this.service.getAll(payload))
        .map(response => this.action.getAllSuccess(response))
        .catch((error: Error) => Observable.of(this.action.getAllFail(error)))
    );

All 4 comments

In this case wouldn't groupBy work more or less for what you're trying to accomplish?

@Effect() getAll$: Observable<Action> = this.actions$
    .ofType("GET_ALL")
    .groupBy(x => x.payload)
    .mergeMap((group) => group.switchMap(({payload}) => this.service.getAll(payload))
        .map(response => this.action.getAllSuccess(response))
        .catch((error: Error) => Observable.of(this.action.getAllFail(error)))
    );

@david-driscoll's answer is correct

Thank you, this is exactly what I needed.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benlesh picture benlesh  路  3Comments

matthewwithanm picture matthewwithanm  路  4Comments

dooreelko picture dooreelko  路  3Comments

samherrmann picture samherrmann  路  3Comments

Zzzen picture Zzzen  路  3Comments