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.
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.
Most helpful comment
In this case wouldn't groupBy work more or less for what you're trying to accomplish?