Reputation: 36219
I have a list of invites in my app, each one with corresponding delete button. When a user clicks delete a DELETE_INVITE
action is dispatched and an epic fire:
const deleteInvite = (action$: any, store: Store<ReduxState, *>) =>
action$.pipe(
ofType(DELETE_INVITE),
mergeMap(({ payload }) =>
ajax(api.deleteInvite(payload.inviteId)).pipe(
map((response: Object) => ({
type: DELETE_INVITE + SUCCESS,
payload: {
data: response.response,
status: response.status,
},
})),
catchError((error: Object) => of({
type: DELETE_INVITE + FAILURE,
error: {
response: {
data: error.xhr.response,
status: error.xhr.status,
},
},
})),
),
),
);
Now I would like to ensure that only one request is fired at the time and wait until last one finished. In other words, I want to protect myself from a situation where user rapidly clicks all over the buttons and fires few request simultaneously.
switchMap
is kind of something I'm looking for because it would handle only most recent click... but the request would be already fired and UI left with outdated data. So I need something that will let call mergeMap
again only when inner chain completes.
Upvotes: 0
Views: 1872
Reputation: 15411
Based on your comments below, it sounds like what you want is exhaustMap
.
Projects each source value to an Observable which is merged in the output Observable only if the previous projected Observable has completed.
const deleteInvite = (action$: any, store: Store<ReduxState, *>) =>
action$.pipe(
ofType(DELETE_INVITE),
exhaustMap(({ payload }) =>
ajax(api.deleteInvite(payload.inviteId)).pipe(
map((response: Object) => ({
type: DELETE_INVITE + SUCCESS,
payload: {
data: response.response,
status: response.status,
},
})),
catchError((error: Object) => of({
type: DELETE_INVITE + FAILURE,
error: {
response: {
data: error.xhr.response,
status: error.xhr.status,
},
},
})),
),
),
);
Upvotes: 1
Reputation: 171
I guess I would ask why you need to use redux-observable to achieve this in the first place. Can't you just set some state variable in your redux store at the start of your request (like deleteInProgress = true), and use this state to disable the delete button. And when your request finishes (either successfully or erroroneously), set the deleteInProgress flag back to false, which will re-enable the button.
Upvotes: 1