Reputation: 53
I have looked this for quite awhile, but I really haven't figured out how to do it "properly". All the other answers are either deprecated or do this in the opposite order.
What I would like to do, is that I want to send a bunch of HTTP request in parallel, thus the forkJoin. Then and only then when they are completed, I would like to call another HTTP request (which is now inside the submitOrder()).
And then at some point, if the first HTTP requests were successful I would like to mark my objects not dirty again.
This code works, but I've understood that this is really not the "proper" way of doing it, because it call subscription inside of a subscription.
So please, what is the real RxJs way?
forkJoin(obsArray).subscribe(res => {
console.log('All were resolved');
this.products.forEach(element => {
this.isNotDirtyAnymore();
});
this.submitOrder();
});
submitOrder() {
this.service.submitOrder(this.id).subscribe(response => {
console.log('Order was submitted');
}, error => {
console.log(error);
});
}
Upvotes: 2
Views: 2809
Reputation: 96891
If you don't need to results from the forkJoin
you could do it like this:
concat(
forkJoin(obsArray),
this.service.submitOrder(this.id)
).subscribe({
complete: () => { // This will be triggered only when `concat` completes which means both source Observables complete (won't emit error).
this.products.forEach(element => {
this.isNotDirtyAnymore();
});
},
})
Make sure you import import { concat } from 'rxjs';
and not from rxjs/operators
.
Upvotes: 2
Reputation: 8258
Here is an example of my comment above (not tested):
forkJoin([
this.service.callItem1,
this.service.callItem2
]).pipe(
tap(([resp1, resp2]: [any, any])=> {
this.products.forEach(element => {
this.isNotDirtyAnymore();
});
}),
switchMap(([resp1, resp2]: [any, any]) => this.service.submitOrder(this.id))
).subscribe(response => {
// if you don't need to do this in the tap above you can do it here
this.products.forEach(element => {
this.isNotDirtyAnymore();
});
console.log('Order was submitted');
}, error => {
console.log(error);
});
Upvotes: 3
Reputation: 465
You can use the pipe operator.
Example from http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html:
import { map, filter, scan } from 'rxjs/operators';
Rx.Observable.interval(1000)
.pipe(
filter(x => x % 2 === 0),
map(x => x + x),
scan((acc, x) => acc + x)
).subscribe(x => console.log(x))
Upvotes: 0
Reputation: 149
As forkJoin
actually return a new observable, you can just treat is as a normal observable. Then a normal hight order operator could be used, switchMap, contactMap... And put the side effect into tap. For example:
forkJoin(obsArray).pipe(
tap(() => {
console.log('All were resolved');
this.products.forEach(element => this.isNotDirtyAnymore()),
}),
switchMap(() => submitOrder()),
});
Upvotes: 2