0

I have done quite a bit of research before deciding to post the questions here. My knowledge of how Angular (or generally) handles HTTP error is very cloudy, so I am looking for some clarification/suggestion.

To make things simple, let's say I have a rest API GET http://example.com that will returns {error: 'Error message'} or {data: 'Data is available'} randomly where error indicates something went wrong (the request completed successfully, but there is some internal error) and data indicates that everything works fine.

Now, there are 2 things that, to my understanding, need handling. The first thing is to handling when the request fails, for example, network error, blocked by CORS, etc., and the second thing is to handle a successful request, but see if it is error or data.

TL;DR: How can I transform the below jQuery into Angular?

Normally, with jQuery, this is what I would do:

$.get('http://example.com').done(data => {

    if ('error' in data) console.log('Request completed, but there is an error in the remote server');
    else console.log('Everything completed successfully');

).fail(error => {

    console.log('Error while requesting data', error);

});

Now in Angular, things get complicated and I no matter what I try, I can't seem to throw an error (all functions are properly imported):

//service.ts
    getStatus() {

        return this.http.get('https://test.com/')
        .pipe(
            map(data => {
                if ('error' in data) {
                    //I would like to throw an error that can be caught at subscribe(done, error) later
                    //But this rxjs won't throw anything, subscribe() will still resolve with done()
                    return throwError('Request completed, but there is an error in the remote server');
                }
                return data;
            }),
            tap(data => {
                //Process the data, should not be called if map() throwError()?
            },
            catchError(error => {
                //I assume this is where the HTTP request failed due to network, CORS, etc.
                return throwError('Error while requesting data');
            })
        );

    }
//app.ts
    this.service.getStatus().subscribe(data => {

        //I expect this function to be called ONLY if there was no throwError(), but that wasn't the case
        //No matter what I try in `service.ts`, this will always be called

    }, (error) => {

       //I expect this to call when throwError() is called from `service.ts` but it never happens

    });

I also read another suggestion to use catch() on subscribe() but catch() was never a method on a Subscription:

//app.ts
    this.service.getStatus().subscribe(data => {

        //I expect this function to be called ONLY if there was no throwError(), but that wasn't the case
        //No matter what I try in `service.ts`, this will always be called

    }).catch(error => {

        //This is not valid

    });

None of what I tried has worked, and there are multiple places within the pipe I can throwError() but I'm not quite sure what their differences are (example, catchError() in service.ts and error from subscribe(success, error) in app.ts.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
timthekoder
  • 415
  • 5
  • 16
  • This actually will throw an error as I expected! Can you please put it up as an answer so I can accept it somehow? – timthekoder May 07 '20 at 00:03

1 Answers1

1

Seems a bit complicated to me. If you don't want to implement an http interceptor, I would simply do something like this

//service.ts
  getStatus() {
    return this.http.get('http://www.test.com');
  }

And then

//app.ts
    this.testService.getStatus()
      .subscribe(data => {
        if ('error' in data) {
          // process Error       
          return;
        }
        // process data
        console.log(data);
      }, error => {
        // http error
        console.log(error);
      });

For the tap operator, it is used to perform whatever action you want involving the data or not (such as logging) but it will always return an observable identical to its source.

François Minh
  • 206
  • 2
  • 6