【问题标题】:angular wait for variable is defined角度等待变量被定义
【发布时间】:2016-02-14 11:20:22
【问题描述】:

我有 2 个控制器和一个服务:

angular.module('objDescApp', ['ui.router', 'ui.bootstrap']);
angular.module('objDescApp').config(['$stateProvider', '$urlRouterProvider', '$httpProvider', function ($stateProvider, $urlRouterProvider, $httpProvider) {
                'use strict';
                $urlRouterProvider.otherwise('/');

                $stateProvider
                .state('object', {
                   url: '/{name}',
                   views: {
                        "body": {
                            controller: 'ObjectDetailCtrl',
                            template: '...'
                        }
                });


angular.module('objDescApp').controller('ObjectListCtrl', function ($scope, $state, ConfigService) {
  ConfigService.getConfig(function(){//get config from server
   $scope.object = ConfigService.fillConfigForObjList(); //use config
  }
}

angular.module('objDescApp').controller('ObjectDetailCtrl', ['$scope', '$stateParams', 'ConfigService',  function ($scope, $stateParams, ConfigService) {
   $scope.current_object = ConfigService.fillConfigForObjDetail(); //use config
}

angular.module('objDescApp').factory('ConfigService', function ($http, $rootScope) {
  var jsonConf;
  var confTemplate = {"sometemplate" : {}};

  function fillConfigForObjList (){
     ... //use jsonConf variable , and always wait for init because of called only inside callback function of getConfig();
  };
  function fillConfigForObjDetail(){
    ... //use jsonConf variable , but doesnt wait for jsonConf  initialization, so error var 'is undefined' here.So I need to add some waiting for 'jsonConf' initialization logic here

   };

   return {
              jsonConf: jsonConf,
              fillConfigForObjDetail: fillConfigForObjDetail,
              fillConfigForObjList: fillConfigForObjList,
              getConfig: function(callback){           
                            $http({
                              method: 'GET',
                              url: endPointUrl,
                              transformResponse: undefined
                            }).then(
                                function successCallback(response) {
                                    jsonConf = JSON.parse(response.data);
                                    $rootScope.getConfigError = false;
                                    callback();
                                },
                                function errorCallback(response) {
                                    if(response.status == "404"){
                                        jsonConf = confTemplate;
                                    }else{
                                        console.log("Get config error");
                                        jsonConf = confTemplate;
                                        $rootScope.getConfigError = true;
                                    }
                                    callback();
                                }
                            );
                        }
    }

所以,当我用主路径 '/' 加载页面时,一切正常,因为 'ObjectListCtrl' 控制器触发了 getConfig() 函数在响应后设置 'jsonConf' 变量,因此我可以在任何状态之间导航并且一切正常,因为已经设置了 'jsonConf';

但如果我重新加载页面的起始路径状态类似于 '/{name}' ,那么 'ObjectListCtrl' 控制器会触发 'getConfig()' 对服务器的请求,但以异步方式触发了 'ObjectDetailCtrl' 控制器及其 $scope.current_object = ConfigService.fillConfigForObjDetail() 表达式,该表达式抛出 @987654322 @ 那么有人可以告诉我如何在“fillConfigForObjDetail()”函数中等待,直到 getConfig() 函数初始化“jsonConf”变量。

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    保存承诺并从承诺中

       var jsonConfPromise;
    
       function getConfig() {
           //save httpPromise           
           jsonConfPromise = $http({
                                  method: 'GET',
                                  url: endPointUrl,
                                  transformResponse: undefined
                                }).then(
                                    function successCallback(response) {
                                        jsonConf = JSON.parse(response.data);
                                        $rootScope.getConfigError = false;
                                        //return for chaining
                                        return jsonConf;
                                    },
                                    function errorCallback(response) {
                                        if(response.status == "404"){
                                            jsonConf = confTemplate;
                                        }else{
                                            console.log("Get config error");
                                            jsonConf = confTemplate;
                                            $rootScope.getConfigError = true;
                                        }
                                        //return for chaining
                                        return jsonConf;
                                    }
                                );
           //return promise
           return jsonConfPromise;  
       };
    

    你有问题的函数然后可以链接承诺。

    function fillConfigForObjDetail(){
        /*
        ... //use jsonConf variable , but doesnt wait for jsonConf
        initialization, so error var 'is undefined' here.
        So I need to add some waiting for 'jsonConf' initialization
        logic here
        */
    
        //chain from the promise
        jsonConfPromise.then(function (jsonConf) {
            //use resolved jsonConf
        });
    };
    

    同样在您的控制器中,而不是使用回调,返回的承诺。

    angular.module('objDescApp').controller('ObjectListCtrl', function ($scope, $state, ConfigService) {
        var configPromise = ConfigService.getConfig();
        configPromise.then(function() {
             $scope.object = ConfigService.fillConfigForObjList();
        });
    });
    

    AngularJS 框架使用 promises 而不是 callbacks

    有关链接承诺的更多信息,请参阅AngularJS $q Service API Reference -- chaining promises

    因为调用 Promise 的 then 方法会返回一个新的派生 Promise,所以很容易创建一个 Promise 链。可以创建任意长度的链,并且由于可以使用另一个 Promise 来解决一个 Promise(这将进一步推迟其解决方案),因此可以在链中的任何点暂停/推迟对 Promise 的解决。这使得实现强大的 API 成为可能。1

    【讨论】:

      猜你喜欢
      • 2018-07-05
      • 1970-01-01
      • 2011-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多