Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJs - forkJoin with empty array

Tags:

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(() => ...)) } 
like image 327
LppEdd Avatar asked Nov 26 '18 09:11

LppEdd


People also ask

Is forkJoin deprecated?

forkJoin Improvements Moreover, there is one deprecation — forkJoin(a, b, c, d) should no longer be used; Instead, pass an array such as forkJoin([a, b, c, d]) .

What can I use instead of forkJoin?

concat() which will handle each observable in sequence.

Does forkJoin complete?

As forkJoin only completes when all inner observables complete, we must be mindful if an observable never completes.

Does forkJoin maintain order?

Yes it will be in the same order. The documentations says following : "forkJoin will wait for all passed Observables to complete and then it will emit an array with last values from corresponding Observables.


2 Answers

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

like image 193
martin Avatar answered Sep 17 '22 03:09

martin


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'); }); 
like image 24
Philip John Avatar answered Sep 19 '22 03:09

Philip John