3

I have a service that contains a generic call to $http that all ajax calls uses. Here I have "centralized" error handling where the status codes results in redirects.

"FieldsSync" service:

return $http({
    method: 'POST',
    url: url,
    data: $.extend(defaultPostData, postData)
}).error(function(data, status) {
    switch (status) {
        case 401: // "Unauthorized". Not logged in. 
            redirect.toLoginPage();
            break;
        case 403: // "Forbidden". Role has changed.
            redirect.toLogoutPage();
            break;
    }
});

When calling one of the service functions from the controller I always return the deferred object to be able to hook up more error callbacks to be able to handle errors that should result in some kind of feedback for the user.

Controller:

fieldsSync.createField(newField).success(function(data) {
    ...
}).error(function(data, status) {
    switch (status) { // <--- DO NOT WANT
        case 401:
        case 403:
            return; // These errors are handled (=redirects) in the generic error callback and we don't want to show do anything while it redirects.
    }
    ... // "Individual" error handling. =Displaying messages and stuff
});

But because I don't want error messages popping up before the redirect occurs I have to exit the error callback if the status codes already have been handled.

The question is: How do i get rid of the switch cases in my controllers? Is it possible to exit the chain of error callbacks when a specific error code has been handled? Or is it possible to work around this in a less ugly way? :)

This is a reoccurring problem for me, and my mind seems stuck.

I have checked the docs and cant find any pretty solution for this in either $http or $q.

2
  • why do you want to do that, If somebody wants handle a particular error status again let him enjoy Commented Apr 5, 2013 at 8:24
  • Having feedback just popping up for a few milliseconds and then disappears because the redirection is occurring doesn't look very nice. I don't see a point of doing something other then a redirect on 401. Commented Apr 5, 2013 at 8:42

2 Answers 2

1

I propose you to use a responseInterceptor to handle those cases:

http://docs.angularjs.org/api/ng.$http

I wrote the following, when I had the same "problem" as you. Its only a first draft, but you can improve it to your needs

InternalServerErrorResponseInterceptor = function($q, InternalServerErrorService) {
    return function(promise) {
        return promise.then(function(response) {
            return response;
        }, function(response) {
            if (response.status > 499) {
                InternalServerErrorService.handleError();
                return $q.reject(response);
            }
            return $q.reject(response);
        });
    };
};
module.factory('InternalServerErrorResponseInterceptor', ['$q', 'InternalServerErrorService', InternalServerErrorResponseInterceptor]);
module.config(['$httpProvider', function($httpProvider) {
        $httpProvider.responseInterceptors.push('InternalServerErrorResponseInterceptor');
    }]);

Now your specific InternalServerErrorService can handle it the way you want it to be handled :)

regards

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

Comments

0

One solution I come up with is to redo the sync functions (puh!) so that they DONT'T return the deferred object. The functions inside the service could take the callbacks as arguments. I could then check if the error already has been handled by the generic error handling before it is called.

Pseudocode:

Service:

fieldsSync.createField(newField, successCallback, failCallback) {
    ...
    genericErrorHandlerResultingInRedirects()
    if (not 401 || 403) {
        failCallback()
    }
};

Controller:

fieldsSync.createField({}, function successCallback(){}, function failCallback(){
    /* Handle errors that should give the user feedback */
});

Other solutions are most welcome.

Comments

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.