20

Is it possible to continue forkjoin http.get requests even if one of the requests fails.

I'm looking to a similar function of $q.allSettled in angular2.

See example : http://jsfiddle.net/Zenuka/pHEf9/

angular.module('qAllSettled', []).config(function($provide) {
  $provide.decorator('$q', function($delegate) {
    var $q = $delegate;
    $q.allSettled = function(promises) {
      return $q.all(promises.map(function(promise) {
        return promise.then(function(value) {
          return { state: 'fulfilled', value: value };
        }, function(reason) {
          return { state: 'rejected', reason: reason };
        });
      }));
    };
    return $q;
  });
});

Kab

kabus
  • 899
  • 1
  • 11
  • 20

2 Answers2

33

You could leverage the catch operator for each observable to intercept the error and return another observable in such cases.

Here is a sample:

return Observable.forkJoin(
  this.http.get('/some-url')
         .map((res:Response) => res.json())
         .catch(res:Response => Observable.of({}),
  this.http.get('/some-other-url')
         .map((res:Response) => res.json())
         .catch(res:Response => Observable.of({}),
);
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • it is so annoying to return null\undefined\{} against just return empty() or use rxjs filter, but empty() or filter() 're not working with forkJoin cause of needs "to requires all source Observables to emit at least one value" as mentioned in https://stackoverflow.com/a/50130620/9928564 . Its sadly to use "this" approach in 2020 – Den Kerny Apr 22 '20 at 09:48
3

Uses Observable.forkJoin() to run multiple concurrent http.get() requests. The entire operation will result in an error state if any single request fails.

 getBooksAndMovies() {
    return Observable.forkJoin(
      this.http.get('/app/books.json').map((res:Response) => res.json()),
      this.http.get('/app/movies.json').map((res:Response) => res.json())
    );

But you could put your additional GET request in the error handler:

getBooksAndMovies() {
    Observable.forkJoin(
        this.http.get('/app/books.json').map((res:Response) => res.json()),
        this.http.get('/app/movies.json').map((res:Response) => res.json())
    ).subscribe(
      data => {
        this.books = data[0]
        this.movies = data[1]
      },
      err => console.error(err)
    );
null canvas
  • 10,201
  • 2
  • 15
  • 18
  • Thanks for the response, can you provide an example? – kabus Jun 27 '16 at 12:42
  • 10
    downvote because this does not solve the OPs question of how to continue the requests if one of them fails. Does forkJoin await completion of non-failing requests or does it immediately fail itself? – corolla Feb 20 '17 at 15:20
  • 1
    @AngJobs Is there a way to handle the errors for each array element? I need to update the UI with an error message for the specific element that fails. I've added an (err) => {} after the res: block but it just jumps to the final fail for the entire array – Adam Mendoza Feb 28 '17 at 07:19