2

I have a component with this:

      this.loginService.login(this.user, () => {
        this.router.navigateByUrl('/');
      });

And a service with this method:

    login(credentials, callback) {
        const headers = new HttpHeaders(credentials ?
            { authorization: 'Basic ' + btoa(credentials.email + ':' + credentials.password) }
            : {});

        this.http.get(this.API.crudAdmin + 'admin?email=' + credentials.email,
            { headers: headers }).subscribe(response => {
                if (response['name']) {
                    this.authenticated = true;
                } else {
                    this.authenticated = false;
                }
                return callback && callback();
            }, error => {
                throw new Error('Error');
            });
    }

How could I catch the error thrown from login method when I call it from the component?

3 Answers 3

2

You can pass in an error callback function along with the success callback. The error callback would be called when the GET request fails:

this.loginService.login(this.user,
  () => this.router.navigateByUrl('/'),
  //handle the error here, log to an error service etc.
  (err) = > console.error(err)
);

On the service side, in the error handler of the Observable, you call the errorCallback you have passed from the component:

login(credentials, successCallback, errorCallback) {
  const headers = new HttpHeaders(credentials ? {
      authorization: 'Basic ' + btoa(credentials.email + ':' + credentials.password)
    } :
    {});

  this.http.get(this.API.crudAdmin + 'admin?email=' + credentials.email, {
    headers: headers
  }).subscribe(response => {
    if (response['name']) {
      this.authenticated = true;
    } else {
      this.authenticated = false;
    }
    successCallback && successCallback();
  }, 
  errorCallback);
}

A traditional try-catch won't work here as this is an asynchronous operation, the catch block won't be able catch the error when the GET fails eventually.

This is because the loginService.login method returns immediately while the GET request is made asynchronously in the background. Any error from the GET won't be handled by the catch block surrounding the loginService.login call.

Sign up to request clarification or add additional context in comments.

Comments

2

It's a common pattern to pass the error as the first argument in the callback function. So your login function would look like:


login(credentuals, callback) {
  this.http.get(options).subscribe((response) => {
    // Logic, assuming it was successfuly, call callback with the first argument as null
    callback(null)
  }, (error) => {
    // in the event of an error, pass error exception as the first argument
    callback(error)
  });
}

so then you can handle this in your component:

this.loginService.login(credentials, (error) => {
  if (error) {
    // show error dialog, etc
  } else {
    this.router.navigateByUrl('/');
  }
})

Comments

0

You can surround your function call in a try/catch block.

try {
    this.loginService.login(this.user, () => {
        this.router.navigateByUrl('/');
    });
} catch (error) {
    // do something with the thrown error
}

2 Comments

Won’t help if the error is thrown from inside the callback (eg. navigateByURL throws).
That's true. I didn't see he mentioned the callback in the title, but rather just the error the login method throws in the question body. Either way, the question looks answered already so I'll leave this as is.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.