Reputation: 1098
I work in angular 2 Project and use ngrx and rxjs technologies.
Now I have a problem:
I try to declare an Effect. The effect has http request, and only when it success I want to call other http-request, and so only if it also success - then dispatch an success-action.
I has tested it by throw an error but it always dispatch the action!
See:
@Effect()
createEntity$ = this.actions$.ofType(CREATE_ENTITY)
.switchMap((action: CreateEntity) => {
return this.httpService.getDefaultEntityData(action.payload.type).map((entity) => {
return Observable.throw("testing only");
/*if (entity) {
entity.title = entity.type;
return this.httpService.addEntity(entity);
}*/
})
.catch((error) => Observable.of(new createEntityFailure(error)))
.map(mappedResponse => ({ type: CREATE_ENTITY_SUCCESS, payload: mappedResponse }))
});
Upvotes: 0
Views: 768
Reputation: 1243
1) If you returning Observable
you probably want swithMap
instead of map
2) Action always has been dispatched because you return non error Observable
from catch
. Changing Observable.of
to Observable.throw
will throw error further
@Effect()
createEntity$ = this.actions$.ofType(CREATE_ENTITY)
.switchMap((action: CreateEntity) =>
this.httpService.getDefaultEntityData(action.payload.type)
)
.switchMap((entity) => { // <------ switchMap here
return Observable.throw("testing only");
/*if (entity) {
entity.title = entity.type;
return this.httpService.addEntity(entity);
}*/
})
.catch((error) =>
Observable.throw(new createEntityFailure(error)) // <------ throw here
)
.map((mappedResponse) =>
({ type: CREATE_ENTITY_SUCCESS, payload: mappedResponse })
);
Upvotes: 1
Reputation: 607
You can either split this up into multiple actions or just add another API call in the same effect using Observable.forkJoin
@Effect() createEntity$ = this.actions$.ofType(CREATE_ENTITY)
.switchMap((action: CreateEntity) => {
return Observable.forkJoin(
this.httpService.callOne(),
this.httpService.callTwo()
)
.catch((error) => Observable.of(new createEntityFailure(error)))
.map(mappedResponse => ({ type: CREATE_ENTITY_SUCCESS, payload: mappedResponse }))
});
As forkJoin is parallel that won't work for you. You can just switchMap on the first API call and return the second:
@Effect() createEntity$ = this.actions$.ofType(CREATE_ENTITY)
.switchMap((action: CreateEntity) => {
return this.httpService.callOne();
})
.switchMap((response) => {
return this.httpService.callTwo()
.map(secondResponse => ({
type: CREATE_ENTITY_SUCCESS,
payload: {
first: response,
second: secondResponse
}
}))
})
.catch((error) => Observable.of(new createEntityFailure(error)))
});
Upvotes: 1
Reputation: 3518
How about this:
this.actions$
.ofType(CREATE_ENTITY)
.map((action: CreateEntity) => action.payload)
.switchMap(payload =>
this.httpService.getDefaultEntityData(payload.type)
.mergeMap(entity => this.httpService.addEntity(entity))
// .mergeMap(entity => Observable.throw('error')) // or this for testing
.mergeMap(response => new actions.Action(...))
.catch(error => new actions.Error(...))
);
Upvotes: 1