occasl occasl - 4 years ago 242
TypeScript Question

Observable subscription not getting called

I have an Observable that I'm using to convert a promise into a subscription. This results in a collection that I need to iterate through to call an HTTP Service on each element. I'm using forkJoin to wait for all those calls to finish so that I can do something else, but unfortunately, my subscription is not being called. Do you see what I'm missing here?

Observable.fromPromise(this.users.getElements()).subscribe(results => {
Observable.forkJoin(
results.map(
aUser => this.HttpService.submitUser(aUser).subscribe(
results => {
this.progress += 1;
},
err => {
this.progress += 1;
this.handleError(<any>err);
})
).subscribe(
//it never gets to either of these calls after all service calls complete
data => {
debugger;
console.log(data);
this.reset();
},
err => {
debugger;
console.log(err);
this.reset();
}
));
});

Answer Source

One thing is you don't subscribe to each Observable passed to forkJoin(). The operator has to do it itself.

If you want to be notified when each Observable completes you can use .do(undefined, undefined, () => {...}).

let observables = [
  Observable.of(42).do(undefined, undefined, () => console.log('done')),
  Observable.of('a').delay(100).do(undefined, undefined, () => console.log('done')),
  Observable.of(true).do(undefined, undefined, () => console.log('done')),
];

Observable.forkJoin(observables)
  .subscribe(results => console.log(results));

This prints to console:

done
done
done
[ 42, 'a', true ]

Eventually there's also .finally() operator. However, it's not the same as using .do().

EDIT:

When any of the source Observables fail the forkJoin() operator reemits the error (which means it also fails).
This means you need to catch errors in each source Observable separately (with catch() operator for example).

let observables = [
  Observable.throw(new Error())
    .catch(() => Observable.of('caught error 1'))
    .do(undefined, undefined, () => console.log('done 1')),

  Observable.of('a')
    .delay(100).catch(() => Observable.of('caught error 2'))
    .do(undefined, undefined, () => console.log('done 2')),

  Observable.of(true)
    .catch(() => Observable.of('caught error 3'))
    .do(undefined, undefined, () => console.log('done 3')),
];

Observable.forkJoin(observables)
  .subscribe(results => console.log(results));

Which prints:

done 1
done 3
done 2
[ 'caught error 1', 'a', true ]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download