【问题标题】:Resolve multiple promises in route's resolve before initializing controller在初始化控制器之前解决路由解析中的多个承诺
【发布时间】:2016-12-22 15:30:18
【问题描述】:

在初始化我的控制器之前,我需要重新调用 2 个 http 调用,当前使用 Angular UI 路由器,并且我在 $stateProvider.state('stateName', {stateObject}) 下解析了我的 stateObject 下的映射,如下所示

    $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) 的 then(function(){}),这是出乎意料的行为,我相信 deferredObj 的所有承诺映射都应该在之前解析这条线被执行,我的控制器被初始化,尽管其中一个承诺被解决了

【问题讨论】:

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


    【解决方案1】:

    由于$q.all$http.then 方法都返回promise,因此无需使用$q.defer 制造promise。仅使用 $q.defer 从旧式仅回调异步 API 做出承诺。

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

    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 创建一个复合 Promise。

    使用派生的 Promise 的优点是拒绝会自动结转到最终的 Promise。如当前所写,$q.defer 方法将在任何一个 XHR 调用有来自服务器的错误时挂起状态更改。

    【讨论】:

      【解决方案2】:

      我发现了这个问题,这是由于将延迟对象传递给 $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;
              }
          }
      });
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-24
        • 1970-01-01
        • 2017-11-24
        • 1970-01-01
        • 2016-12-06
        • 2015-05-17
        • 2016-03-13
        相关资源
        最近更新 更多