Reputation: 115
I'm returning multiple action from one effect, concatMap send action in order but don't wait for completion to send next action. loadDetails call a REST service and update store when he receive loadDetailsSuccess
I want to finish loadDetailsAction before calling HttpResultActions.httpRequestUpdateSuccessful().
How can achieve that? From a different action?
@Effect()
removeLibelle$ = this.actions$
.ofType(DetailsActions.DELETE_LIBELLE)
.map(toPayload)
.withLatestFrom(this.store$.select(state => state.tree))
.switchMap(([payload, tree]) => this.libelleService.deleteItem(payload)
.concatMap(() => {
return [
DetailsActions.clear(), //function dispatch action clear
DetailsActions.loadDetails({ entity: tree.entity,
dateSearch: tree.search.dateSearch }), //function dispatch GET
HttpResultActions.httpRequestUpdateSuccessful() //Dispatch action to show modal success
];
}).catch(error => Observable.of(HttpResultActions.httpRequestError(error))));
Upvotes: 5
Views: 3911
Reputation: 9331
You are doing too many things in single effect. You can liberally break it into multiple effects . Think it this way.
DELETE ---> perform delete ----> DELETE_SUCCESS , DELETE_ERROR
DELETE_SUCCESS ---> clear data ----> DATA_CLEAR_SUCCESS
DATA_CLEAR_SUCCESS ----> load data ----> LOAD_DATA_SUCCESS
I did the actions in series . You can perform them in parallell also. May be you want to trigger both clear data and load data immediately , then it looks like this :
DELETE ---> perform delete ----> DELETE_SUCCESS , DELETE_ERROR
DELETE_SUCCESS ---> clear data ----> DATA_CLEAR_SUCCESS
DELETE_SUCCESS ----> load data ----> LOAD_DATA_SUCCESS
Now you can perform model changes in any of these actions. Interesting part is , you may have same model change for get http call or get http call after delete is success. That is the beauty of redux.
Your code looks like this
@Effect()
removeLibelle$ = this.actions$
.ofType(DetailsActions.DELETE_LIBELLE)
.map(toPayload)
.withLatestFrom(this.store$.select(state => state.tree))
.switchMap(([payload, tree]) =>
this.libelleService.deleteItem(payload)
)// return DELETE_SUCCESS
.catch() //return DELETE_FAIL
@Effect()
removeLibelleDataClear$ = this.actions$
.ofType(DetailsActions.DELETE_LIBELLE)
//perform DetailsActions.clear(),
//return DATA_CLEAR_SUCCESS action
// return DATA_CLEAR_ERROR action
// If you want to data load in parallell with clear,
// you can listen on delete_success . If you want to do
// it after data_clear, then listen on data_clear_success
@Effect()
removeLibelleDataClear$ = this.actions$
.ofType(DetailsActions.DATA_CLEAR_SUCCESS)
//perform
//DetailsActions.loadDetails({ entity: tree.entity,
// dateSearch: tree.search.dateSearch })
// DATA_LOAD_SUCCESS
//catch: DATA_LOAD_ERROR
You may wish to immediately notify the user that delete is success. And refresh data . Or you can add different action DELETE_SUCCESS_DATA_LOAD_SUCCESS and inform user that delete is success.
Breaking this way makes testing very very easy, compare this with complex switchmap+concat+three http calls.
Upvotes: 5