45

I'm currently using forkJoin to wait for an array of Observable(s) to finish before pipe(ing) and tap(ping).

I noticed if the array is empty nothing is emitted and I cannot even tap. How do I solve this kind of problem? Should I just check if the array is empty?

myFirstFunction(...) {
   const observables = ...
   return forkJoin(observables)
}

mySecondFunction(...) {
   return myFirstFunction().pipe(tap(() => ...))
}

2 Answers 2

80

That's because forkJoin requires all source Observables to emit at least one item and when there are no source Observables there's nothing to emit. However, forkJoin will still send the complete notification so you can use for example defaultIfEmpty operator to make sure it always emits at least one next.

forkJoin(observables).pipe(
  defaultIfEmpty(null),
).subscribe(...);

Demo: https://stackblitz.com/edit/rxjs-kkd1qa?file=index.ts

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Martin. Is the "will still send the complete notification" related only to the forkJoin operator or is it more general?
That's related to forkJoin's internal functionality.
I asked because I was looking at this page learnrxjs.io/operators/combination/forkjoin.html and found nothing mentioning this. Oh btw, had to use defaultIfEmpty([])
This is as edge case so I'm not surprised it's not mentioned there. I don't think this behavior is mentioned not even in the official documentation. You can see that it really works here stackblitz.com/edit/rxjs-kkd1qa?file=index.ts
13

Additionally to martin's answer.

I had 2 observables returning arrays and if one of them gives me an empty array, it did not wait for the other observable to finish and completed instantly. You can handle such cases as follows using defaultIfEmpty.

const response1: Observable<any[]> = this.service.getResponse(params1).pipe(defaultIfEmpty([]));
const response2: Observable<any[]> = this.service.getResponse(params2).pipe(defaultIfEmpty([]));

Observable.forkJoin(response1, response2).subscribe((response) => {
  console.log(response);
}, () => {
  console.log('handle error here');
}, () => {
  console.log('completed');
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.