AngularJS,如何使用$ http的工厂获得解析值?

时间:2015-03-27 11:51:23

标签: angularjs angular-ui-router

我已经使用ui-router声明了一个状态,并尝试执行解析。但是,我无法使用工厂中的$ http返回我的决心中的值。以下是我尝试过的一种方式。

success回调似乎运行得太晚,以至于在解析中实际上没有返回任何内容。当success回调运行时,它会产生所需的结果。

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

1 个答案:

答案 0 :(得分:2)

resolve中,您必须返回promise个对象 - 您无法返回值:

...
.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".
            }]
    },
...

但是,问题中提供的代码使用工厂来检索值。我们必须更改工厂,以便它检索promise。为此,我们注意到success方法返回值,then方法返回一个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"
                });
            }
        };

}

因此,工厂改为:

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
            });
        }
    };
}

resolve变为(阅读代码中的注释):

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