AngularJS handle rejected response with UI-Router

Issue

I have a Service which wraps my API calls in Angular:

var ConcernService = {

    list: function (items_url) {
        var defer = $q.defer();
        $http({method: 'GET', 
            url: api_url + items_url})
            .success(function (data, status, headers, config) {
                defer.resolve(data, status);
            })
            .error(function (data, status, headers, config) {
                defer.reject(data, status);
            });
        return defer.promise;
    },

Then my app config, with UI-Router:

    .config(function($stateProvider){

        $stateProvider

        .state('default', {
            url: '/',
            resolve: {
                tasks: function ($stateParams, ConcernService) {
                    return ConcernService.list('tasks/').then(
                        function (tasks)   { return tasks; },
                        function (reason)  { return []; }
                    );
                },
                ...
            }
        }
    });

This is the most basic configuration I could get away with, which basically just returns an empty object if a 403, 404 etc is encountered and I can handle that in the view, template.

My question is, what is the best approach for getting the other detail to the view/ template, such as the rejection reason and status. Should it be returned in the tasks object, or separately?

Solution

Well, first of all, your first bit of code has the deferred anti pattern, let’s fix that:

list: function (items_url) {
    return $http.get(api_url + items_url); // $http already returns a promise
},

Also note, that deferred rejections and fulfillments are single value, so your multiple return values don’t really work here.

Now, let’s look at the router. First of all, your first fulfillment handler is redundant.

.state('default', {
        url: '/',
        resolve: {
            tasks: function ($stateParams, ConcernService) {
                return ConcernService.list('tasks/'); // result.data contains the data here
            },
            ...
        }

Now, the problem we have here is what happens in case of a rejection?

Well, listen to $stateChangeError:

$rootScope.$on('$stateChangeError', 
function(event, toState, toParams, fromState, fromParams, error){ ... })

Here, you can listen to change state failures from rejections.

Answered By – Benjamin Gruenbaum

Answer Checked By – Robin (AngularFixing Admin)

Leave a Reply

Your email address will not be published.