1

I have declared a state using ui-router and am trying to perform a resolve. However, I cannot return a value in my resolve using a $http in a factory. Below is one way that I've tried.

It appears that the success callback runs too late so that nothing is actually returned inside the resolve. When the success callback does run, it produces the desired result.

...
.state('book', {
    url: '/book',
    abstract: true,
    views: {
        '': { 
            templateUrl: 'templates/book.html',
            controller: bookController
        }
    }
})
.state('book.detail', {
    url: '/{chapter}/{pageName}',
    resolve: {
        pageIdNumber: ['$http','$stateParams', 'myFactory', function($http, $stateParams, myFactory) {
            return myFactory.getPageIdNumberUsingPageName(
                function(response, $stateParams) {return response[0];}, // console.log(response[0]) gives the desired result but nothing is returned. I think this function runs too late.
                function(response) {return response[0];},
                $stateParams.pageName);
            }]
    },
    views: {
        'page@book': { 
             templateUrl: 'templates/page.html',
             controller: pageController
         }
    }
})
...

myFactory.$inject = ['$http'];
function myFactory($http){
    return {
        getPageIdNumberUsingPageName: function (callbackSuccess, callbackError, pageName){
            $http({
                method: 'POST',
                url: 'http://example.com/api/get_page_id.json',
                cache: true,
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                data: 'page_name=' + encodeURIComponent(pageName),
            })
            .success(function (response) {
                callbackSuccess(response);
            })
            .error(function (response) {
                callbackError(response);
            });
        }
    };
}
3
  • 2
    You need to use promise based setup for resolve to work. Callbacks do not work. See this video thinkster.io/egghead/resolve Commented Mar 27, 2015 at 11:53
  • Check an example here stackoverflow.com/q/28237952/1679310... Commented Mar 27, 2015 at 12:05
  • Thanks for your comments. I've posted an answer below. Commented Mar 28, 2015 at 9:32

1 Answer 1

2

In the resolve, you must return a promise object - you cannot return a value:

...
.state('book.detail', {
    url: '/{chapter}/{pageName}',
    resolve: {
        pageIdNumber: ['$http','$stateParams', 'myFactory', function($http, $stateParams, myFactory) {
            return $something; // $something must be a promise object and not a value like "2" or "dog".
            }]
    },
...

However, the code provided in the question uses a factory to retrieve a value. We must change the factory so that it retrieves a promise. To do this, we note that the success method returns values and the then method returns a promise:

    function myFactory($http){
        return {
            getPageIdNumberUsingPageName: function (callbackSuccess, callbackError, pageName){
                $http({
                    ...
                })
                .success(function (response) {
                    // response contains values like "2" and/or "dog"
                });
            }
        };
    }

    function myFactory($http){
        return {
            getPageIdNumberUsingPageName: function (callbackSuccess, callbackError, pageName){
                $http({
                    ...
                })
                .then(function (response) {
                    // response contains a promise object that, when eventually fulfilled, will produce values like "2" and/or "dog"
                });
            }
        };

}

So, the factory changes to:

myFactory.$inject = ['$http'];
function myFactory($http){
    return {
        getPageIdNumberUsingPageName: function (pageName){
            return $http({     // notice the "return" here
                method: 'POST',
                url: 'http://example.com/api/get_page_id.json',
                cache: true,
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                data: 'page_name=' + encodeURIComponent(pageName),
            })
            .then(function (response) {
                return response.data[0]; // data[0] contains the value that I want. response is a promise object
            });
        }
    };
}

And the resolve becomes (read the comments in the code):

...
.state('book.detail', {
    url: '/{chapter}/{pageName}',
    resolve: {
        pageIdNumber: ['$http','$stateParams', 'myFactory', function($http, $stateParams, myFactory) {
            return myFactory.getPageIdNumberUsingPageName($stateParams.pageName); // this returns the $http object in the factory; that factory in turn returns the promise object.
            }]
    },
    views: {
        'page@book': { 
             templateUrl: 'templates/page.html',
             controller: pageController
         }
    }
...
Sign up to request clarification or add additional context in comments.

1 Comment

this seems too complicated

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.