2016-02-14 32 views
1

我有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」可變,所以可以在任何狀態之間naviagte和所有工作正常原因「jsonConf」已經設置好的;

但隨着啓動等路徑狀態「/ {名稱}」如果我重新加載網頁,因此「ObjectListCtrl」控制器trigers 「getConfig()」請求到服務器,但在異步方式「 ObjectDetailCtrl」控制器被觸發及其$ scope.current_object = ConfigService.fillConfigForObjDetail()表達,扔jsonConf is undefined error; 所以有人能告訴我,我怎麼能等在內的‘fillConfigForObjDetail()’函數,直到‘jsonConf’由getConfig變量初始化()函數。

回答

0

保存的承諾和自許。

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框架使用承諾,而不是回調

有關鏈接承諾的更多信息,請參閱AngularJS $q Service API Reference -- chaining promises

因爲調用承諾的then方法會返回一個新的派生承諾,所以很容易創建一個承諾鏈。它可以創建任何長度的鏈,並且自一個承諾可以與另一個承諾(這將進一步推遲其分辨率)來解決,所以能夠暫停/在鏈中的任何點推遲承諾的分辨率。這使得實現強大的API成爲可能。 1