在初始化控制器之前解决路由解析中的多个promise

时间:2016-12-22 15:30:18

标签: angularjs angular-ui-router angular-promise

在初始化我的控制器之前,我需要重新启动2个http调用,当前使用Angular UI路由器,我在$ stateProvider.state('stateName',{stateObject})下解析map我的stateObject as bellow

    $stateProvider.state('stateName', {
        url  : '/myURL',
        params: {
                 data1: undefined,
                 data2 : undefined
            },
        resolve: {
            dataTobeResolve : function($stateParams,$q) {

                var deferred = $q.defer();
                var deferredObj = {};
                deferredObj.d1 = $q.defer();
                deferredObj.d2 = $q.defer();

                var result = {
                    data1: {},
                    data2: {}
                }

                if(angular.isDefined($stateParams.data1)) {
                    result.data1 = $stateParams.data1;
                    deferredObj.d1.resolve();
                }
                else {
                    httpCall().then(function(response) {
                        AsyncMethodCall(response.data).then(function(resolvedData) {
                            result.data1 = resolvedData;
                            deferredObj.d1.resolve();       
                        });
                    });
                }

                if(angular.isDefined($stateParams.data2)) {
                    result.data2 = $stateParams.data2;
                    deferredObj.d2.resolve();
                }
                else {
                    AsyncMethodCall().then(function(resolvedData) {
                        result.data2 = resolvedData;
                        deferredObj.d2.resolve();       
                    });
                }

                $q.all(deferredObj).then(function() {
                    deferred.resolve(result);
                });
                return deferred.promise;
            }
        }
    });

尽管deferredObj.d1正在解析,控制器转到$ q.all(deferredObj)的那个(函数(){})这是意外的行为,我相信deferredObj的所有promise映射应该在之前解决这行被执行,我的控制器初始化,尽管其中一个承诺正在解决

2 个答案:

答案 0 :(得分:1)

由于$q.all$http.then方法都返回promises,因此无需使用$q.defer制作承诺。仅使用$q.defer从旧式回调专用API进行承诺。

使用$q.when从同步源或AngularJS框架外部的承诺中做出承诺。

resolve: {
    dataTobeResolve : function($stateParams,$q) {

        var d1Promise;
        var d2Promise;

        if(angular.isDefined($stateParams.data1)) {
            d1Promise = $q.when($stateParams.data1);
        }
        else {
            d1Promise = httpCall()
              .then(function(response) {
                   return response.data;
            });
        }

        if(angular.isDefined($stateParams.data2)) {
            d2Promise = $q.when($stateParams.data2)
        }
        else {
            d2Promise = httpCall2()
              .then(function(response) {
                  return response.data;      
            });
        }

        return $q.all([d1Promise, d2Promise]);
    }
}

在上面的示例中,两个promise由$ q.when参数创建,或者从基于promise的异步API派生。使用$q.all方法从两个promise中创建复合承诺。

使用派生承诺的优势在于拒绝被自动转移到最终承诺。正如当前所写,如果任一XHR调用从服务器发出错误,$q.defer方法将挂起状态更改。

答案 1 :(得分:0)

我发现了这个问题,这是由于将延迟对象传递给$ q.all()而不是传递的哈希/数组。 所以下面的代码将解决问题

$stateProvider.state('stateName', {
    url  : '/myURL',
    params: {
             data1: undefined,
             data2 : undefined
        },
    resolve: {
        dataTobeResolve : function($stateParams,$q) {

            var deferred = $q.defer();
            var promises = {};
            var d1 = $q.defer();
            var d2 = $q.defer();
            promises.d1 = d1.promise;
            promises.d2 = d2.promise;

            var result = {
                data1: {},
                data2: {}
            }

            if(angular.isDefined($stateParams.data1)) {
                result.data1 = $stateParams.data1;
                d1.resolve();
            }
            else {
                httpCall().then(function(response) {
                    AsyncMethodCall(response.data).then(function(resolvedData) {
                        result.data1 = resolvedData;
                        d1.resolve();       
                    });
                });
            }

            if(angular.isDefined($stateParams.data2)) {
                result.data2 = $stateParams.data2;
                d2.resolve();
            }
            else {
                AsyncMethodCall().then(function(resolvedData) {
                    result.data2 = resolvedData;
                    d2.resolve();       
                });
            }

            $q.all(promises).then(function() {
                deferred.resolve(result);
            });
            return deferred.promise;
        }
    }
});

但如果有人提供更好的解决方案,我仍然感激