3

I have a component based Angular application where the individual components load their respective data. When errors occur I generally want the component to display an error message.

However, in some cases I'd like the component to ignore the error and leave it up to some global error handling mechanism to catch it.

Interceptor:

angular.module("...").factory("httpInterceptor", function($q) {
    return {
        responseError: function(response) {
            // (1)
            return $q.reject("I AM CALLED FIRST") 
        }
})

Serivce:

angular.module("...").service("myService", function($http){
    return {
        fetchData: function(){
            return $http.get("...")    
        }
    }
})

Controller:

angular.module("...").controller("MyController", function(myService){
    myService.fetchData()
        .then(function(){ ... })
        .catch(function() { 
           // (2) 
           //I AM CALLED LAST
        })
})

In most cases i want the error to be handled in the controller (at point (2)). If the controller decides to ignore the error (omit the catch) the error can still be caught in the interceptor.

The problem is that the interceptor doesn't know whether the controller intends to catch the error or not, since it's being called before the controller. Therefore the interceptor does not know whether it should display an error or not (I don't want both a global and a local error message).

How can I catch http errors ignored by the controller?

1
  • To ask the question another way: how can you know if none handled (catched) the error in the promise-chain? Commented Nov 9, 2015 at 9:45

3 Answers 3

7

Since promises do not know a thing about derived promises there seems to be no way to make it beautiful with $http, interceptors and promises.

But here's the ugly way, if you need one:

$httpProvider.interceptors.push(['$q', '$timeout',
        function ($q, $timeout) {
            return {
                responseError: function (response) {
                    $timeout(function () {
                        if (response.errorHandled) {
                            return;
                        }
                        // global AJAX error handling
                    }, 0);
                    return $q.reject(response);
                }
            };
        }
    ]);

And then somewhere in .catch():

.catch(function(response){response.errorHandled = true;})

(I think I saw an answer like this on SO before but I couldn't find it.)

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

3 Comments

Thank you, Dmitry. This is in fact the way I ended up solving it, before you suggested the same solution. I agree it's not pretty, but it works fine. I should perhaps have posted this as an answer to my own question. Sorry about that :-)
the only problem with this solution is that you always have to provide this catch expression, otherwise, the exception will not be handled and you end up with the error in the console(
@AlenaKastsiukavets Uncaught exception (or rather promise rejection in this case) will end up in the global exception handler which most people implement in the way that it logs the error and redirects to the error page. If you'd rather continue with undefined behaviour it is also possible by not implementing the global error handler.
0

if you don't want to handle in controller, you could throw the error and let $exceptionHandler to handle it. you could create a generic error handler in config phase:

$provide.decorator('$exceptionHandler', extendExceptionHandler);

Comments

0

It's a bit hacky but there is a way to add a global fallback error handler for $http requests that fail and don't specify an errorCallback.

Basically, you decorate the $http service so that it fires an 'unhandledHttpError' event when an $http request fails with no errorCallback specified.


This will fire the 'unhandledHttpError' event:

$http.get('/invalid/url').then(function() {
    //success handler
});

This will NOT fire the 'unhandledHttpError' event:

$http.get('/invalid/url').then(function() {
    //success handler
}, function() {
    //error handler
});

To handle the 'unhandledHttpError' event:

$rootScope.$on('unhandledHttpError', function(event, response) {...});

Here is a working example: https://jsfiddle.net/45w6o79p/27/

See the 'myConfig' method in the fiddle for the $http decoration code you'll need to paste into your app to add the 'unhandledHttpError' event.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.