6

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?

1 Answer 1

7

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.

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

2 Comments

Hey Benjamin - thanks for the pointers on my code. I did think it was a little long-winded. I do understand promises a little better now. As for the state change error expression - should this go in my app.config? And then do a just map the various errors to the states I want?
Right. Implementation works. for the record I added the stateChangeError statement to the app.run(), and I can pass along the error object to a generic partial template to display context-specific messages. Thanks!

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.