Reputation: 8879
I have a dialog that when opened dispatches an action to preload data for form controls inside the dialog. The action is picked up by an effect that in turn returns an array of new actions to preload the data for each id
in the array that is passed to the original action.
@Effect()
preloadReferenceData$ = this.actions$
.ofType(PRELOAD_REFDATA)
.pipe(
map((action: PreloadRefData) => action.payload),
mergeMap(ids => {
const actions: Action[] = [];
ids.forEach((id) => actions.push(new LoadRefDataForId(id)));
return actions;
})
);
Normally, I use the mergeMap
operator to successfully dispatch multiple new actions from an effect, though this is the first time I'm dispatching multiple actions of the same type, and it's the first time I've experienced that the XHR calls get cancelled. I would have suspected the use of switchMap
in the case where the XHR calls are cancelled, but not now when I use mergeMap
.
These is the content of actions
LoadRefDataForId {payload: "2441", type: "[Refdata] Load RefData"}
LoadRefDataForId {payload: "7612", type: "[Refdata] Load RefData"}
LoadRefDataForId {payload: "9411", type: "[Refdata] Load RefData"}
and this is taken from the network log
The effect that handles the LoadRefDataForId
action
@Effect()
loadRefDataForId$ = this.actions$
.ofType(LOAD_REFDATA_FOR_ID)
.pipe(
map((action: LoadRefDataForId) => action.payload),
switchMap((id) => this.service.loadRefData(id)
.pipe(
map((occupations) => {
return new LoadRefDataForIdSuccessful({ id: id, occupations: occupations } as RefDataPayload);
}),
catchError((err, caught) => {
console.log(caught);
return caught;
})
))
);
Why are the XHR cancelled, even though I'm using mergeMap
?
Upvotes: 1
Views: 2081
Reputation: 28464
The cancelations are caused by this effect:
@Effect()
loadRefDataForId$ = this.actions$
.ofType(LOAD_REFDATA_FOR_ID)
.pipe(
map((action: LoadRefDataForId) => action.payload),
switchMap((id) => this.service.loadRefData(id)
.pipe(
map((occupations) => {
return new LoadRefDataForIdSuccessful({ id: id, occupations: occupations } as RefDataPayload);
}),
catchError((err, caught) => {
console.log(caught);
return caught;
})
))
);
By using switchMap
in it, you are telling that only the last LoadRefDataForId
action that passes through the actions$
stream should be considered/processed.
Change it to:
@Effect()
loadRefDataForId$ = this.actions$
.ofType(LOAD_REFDATA_FOR_ID)
.pipe(
map((action: LoadRefDataForId) => action.payload),
mergeMap((id) => this.service.loadRefData(id)
.pipe(
map((occupations) => {
return new LoadRefDataForIdSuccessful({ id: id, occupations: occupations } as RefDataPayload);
}),
catchError((err, caught) => {
console.log(caught);
return caught;
})
))
);
Upvotes: 4