Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observable.combineLatest continue even if one fails

I have a function that needs to resolve multiple documents from firebase

  fetchDocuments(documentIds: string[]): Observable<TreeNodeDocument[]> {
    const observables = [];
    for(let id of documentIds){
      observables.push(this.fetchDocument(id));
    }
    return Observable.combineLatest(observables, (...docs: TreeNodeDocument[]) => {
      //some transformations on the resolved documents
      return docs;
    });
  }

this.fetchDocument(id) returns an observable of type TreeNodeDocument.

This function works as long as all of the documents can be resolved. Now sometimes it happens that some of the documents cannot be resolved, then the respective fetchDocument(id) observable will fail. It is ok and expected that some of the documents cannot be resolved. However the Observable.combineLatest fails completely if one of them fails (I understand this is a good default behaviour).

My question is now, can I use combineLatest in a way so I get only the documents on which the fetch has worked and just ignore the ones on which it failed? Or can I achieve this in a different way?

Cheers

like image 720
Tom Avatar asked Sep 10 '18 14:09

Tom


People also ask

Does combineLatest complete?

combineLatest operator returns an Observable that completes when all of the observables passed in as parameters to combineLatest complete.

What is the difference between combineLatest and forkJoin?

forkJoin - When all observables complete, emit the last emitted value from each. combineLatest - When any observable emits a value, emit the latest value from each.

What is observable combineLatest?

combineLatest allows to merge several streams by taking the most recent value from each input observable and emitting those values to the observer as a combined output (usually as an array).


1 Answers

You can pipe each source Observable (each this.fetchDocument(id)) with catchError that will replace the error notification with a dummy next item (or whatever you want).

for (let id of documentIds){
  observables.push(this.fetchDocument(id).pipe(
    catchError(() => of(null)),
  ));
}

...

Note, that you can't use just empty() or of() because both of them wouldn't emit any next item and combineLatest wouldn't work as you expect. Of course, instead of null you can use anything you want. The array of docs will have null at indices where a source Observable failed.

like image 194
martin Avatar answered Oct 30 '22 19:10

martin