1

For the function below, how can I throw an error from the 'BROKEN' like that can be handled nicely by its subscriber in the same way as the 'WORKS' line of code?

What I'm seeing is that the 'Works' line passes the error neatly this function's subscriber, whereas the BROKEN line just blows up without getting handled by its subscriber. I'm using Angular (version 5.0.3) in an Ionic project, RXJS version 5.5.2, and the HttpClient in @angular/common/http.

public makeRequest(requestParameters) {

  return Observable.create(observer => {

    let url = 'http://example.com/service/action?a=b';

    this.http.get(url,{withCredentials: true})
      .subscribe(data => {
        if(data["success"] !== true)
          observer.error("Unexpected result");//BROKEN
        else
          observer.next(data["payload"]);
      },
      err => {
        console.log('error: ' + err);
        observer.error(err);//WORKS
      });
    });
}

Here's an example of a function that calls the one above:

public getStuffFromServer(){
  this.makeRequest({parameters go here}).subscribe(
      data => {
        //do something with the results
      },
      err => {
        //This never gets called from the 'BROKEN' code (but it does from the WORKS code
      }
    );
}

Thanks for your help!

Scott Reece
  • 395
  • 1
  • 3
  • 13

3 Answers3

0

So the problem seems to be that in the line:

if(data["success"] !== true)
    observer.error("Unexpected result");//BROKEN`

The subscription at this point hasn't experienced an error, in fact the subscription has returned data.

Try:

 observer.next(false);

Or something similar.

Faraji Anderson
  • 653
  • 6
  • 18
  • In this case, if data["success"] is false, there was an exception thrown on the server. I intend to pass the details of that exception to all the subscribers without having them look in 2 ways for failures. Thanks for the thought though! – Scott Reece Jan 25 '18 at 22:34
0

OK, it looks like I found the answer on this page: https://codingblast.com/rxjs-error-handling/

The key is to use the map and catch functions like so:

public makeRequest(requestParameters) {

return Observable.create(observer => {
let url = 'http://example.com/service/action?a=b';
this.http.get(url,{withCredentials: true})
  .map(data => {
    if(data["success"] !== true)
      throw new Error("Something meaningful");
    return data["payload"];
   })
  .catch(err => {
    return Rx.Observable.throw(err);
   });
  .subscribe(data => {
      observer.next(data);
  },
  err => {
    console.log('error: ' + err);
    observer.error(err);
  });
});
}

Hopefully this will help somebody. Thank you everyone who answered or gave it some thought!

Scott Reece
  • 395
  • 1
  • 3
  • 13
0

Here is a complete working example how to get internet connection for both, device and browser. Using Angular 7 and RxJs 6.3.3:

The service:

import {
  Injectable
} from '@angular/core';
import {
  Network
} from '@ionic-native/network';

import {
  Platform
} from 'ionic-angular';

import {
  Observable,
  fromEvent,
  merge,
  of
} from 'rxjs';

import {
  mapTo
} from 'rxjs/operators';

@Injectable()
export class NetworkService {

  private online$: Observable < boolean > = null;

  constructor(private network: Network, private platform: Platform) {
    this.online$ = Observable.create(observer => {
      observer.next(true);
    }).pipe(mapTo(true));
    if (this.platform.is('cordova')) {
      // on Device
      this.online$ = merge(
        this.network.onConnect().pipe(mapTo(true)),
        this.network.onDisconnect().pipe(mapTo(false)));
    } else {
      // on Browser
      this.online$ = merge( of (navigator.onLine),
        fromEvent(window, 'online').pipe(mapTo(true)),
        fromEvent(window, 'offline').pipe(mapTo(false))
      );
    }
  }

  public getNetworkType(): string {
    return this.network.type
  }

  public getNetworkStatus(): Observable < boolean > {
    return this.online$;
  }

}

Wherever you need to check just import the service and use just like this:

...
    this.networkService.getNetworkStatus().subscribe((isConnected: boolean) => {
     console.log('Is it connected? '+isConnected);
    });
...
Francisco Souza
  • 806
  • 15
  • 38