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

AngularJS, How to get resolve value using a factory with $http?

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

似乎 success 回调 运行 太晚了,因此在解析中实际上 return 什么也没有。当 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);
            });
        }
    };
}

resolve 中,您必须 return 一个 promise 对象 - 您不能 return 一个值:

...
.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 方法 return 的值和 then 方法 return 的一个承诺:

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