I'm very new to RxJs
and NgRx store
, I'm want to create an @Effect
with combination of two observables (very difficult to explain):
My interfaces looks like:
export interface ProductDetails {
product: Product;
productBody: ProductBody;
}
export interface ProductBody{
id: string;
body: string;
}
I'm trying to create a new objectproductDetails
and set it's properties.
properties are product
which payload
has product
and productBody
which gets it from productService(id)
(It returns observable<productBody>
)
This effect should return observable<productDetails>
@Effect()
getProductDetails$ = this.actions$
.ofType(ProductActions.GET_STEP)
.map(action => action.payload)
.flatMap(s => {
let body;
this.productService.getStepBody(s.id).subscribe(x => body = x);
return Observable.of({
step: s,
productBody: body
});
})
.map(res => this.productActions.getProductDetailsSuccess(res));
this returns:Object {productBody: undefined, product: Object}
I understand why is returning undefined
for productBody
but not sure how to fix it. I tried using zip
, switchMap
and etc but no chance!
Here is what you can do.
flatMap
over the original observable to get the payload.id
to give it to the getStepBody
observable.flatMap
, you want to map
on the getStepBody
observable to return a new value that is a composite object of the payload
and the response of the getStepBody
. subscribe
to get the final result.It looks something like this:
getProductDetails$ = this.actions$
.ofType(ProductActions.GET_STEP)
.map(action => action.payload)
.flatMap(payload => this.productService.getStepBody(payload.id).map(body => ({step: payload, productBody: body})))
.subscribe(res => this.productActions.getProductDetailsSuccess(res)); //res is an object of {step: payload, productBody: body}
If you are not wanting to return the whole object into a single function in the subscribe
function, you could destructure the values to make them easier to consume separately. To that change the subscribe
line to:
.subscribe(({step, body}) => {//do something with each value});