Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle Angular $http errors locally with fallback to global error handling

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?

like image 658
Kristian S Avatar asked Mar 14 '23 05:03

Kristian S


1 Answers

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.)

like image 159
Dmitry Avatar answered Apr 23 '23 09:04

Dmitry