2015-12-01 91 views
0

我在角度上遇到了很奇怪的問題。我已經在run方法中定義了$ rootScope.user_info。但是當我在控制器中獲取根作用域時,有時我會在控制器中獲取未定義的方法$ rootScope.user_info。任何想法爲什麼這有時會發生,當我刷新頁面?

這裏是代碼片段,

myApp.run(['$http', '$rootScope','$location','localStorageService','$window','$translate','$timeout', function($http, $rootScope,$location,localStorageService,$window,$translate,$timeout) { 
    $rootScope.current_user_id = localStorageService.get("CurrentUserId"); 
    $rootScope.get_user_profile = function() { 
     $http.get('/api/v1/employees/'+$rootScope.current_user_id).success(function(response) { 
      $rootScope.user_info = response["data"]["user_info"]; 
     }); 
    }; 

    if ($rootScope.current_user_id) { 
     $rootScope.get_user_profile(); 
    } 
}]); 

myApp.controller('ProfileCtr', ['$rootScope','$scope','Employee','fileReader','$translate','$filter','checkResponse','toaster', function($rootScope,$scope, Employee,fileReader,$translate,$filter,checkResponse,toaster){ 
    $scope.langs = [ { name: "en",value: "English"}, { name: "de_DE", value: "German"}, { name: "fr_FR", value: "French"} ]; 
    $scope.set_language = function() { 
     $scope.selectLang = $filter('filter')($scope.langs, { name: $rootScope.user_info.eselected_language})[0]; 
    } 
    $scope.set_language(); 
}); 
+0

檢查$ rootScope.user_info控制檯run方法的內在價值。看看它是否在那裏。 – Ved

+0

@Ved如果我把console.log放在$ http回調裏面,而不是打印這個對象,但是如果我把console.log放在get_user_profile回調的外面,比打印未定義的 – user9392255

+0

等。我正在爲此工作。 – Ved

回答

0

$rootScope.user_info$http.get回調,這是異步方法定義。當你輸入或刷新你的頁面時,當然它比你嘗試訪問$rootScope.user_info對象的時間晚。因此,編寫這樣的代碼是不好的做法。使用異步功能時,必須使用callbackspromises

0

想象以下:

  1. $rootScope.get_user_profile使得該最終花10分鐘的HTTP請求。
  2. $scope.set_language被調用,它試圖訪問$rootScope.user_info.eselected_language,並失敗。
  3. 十分鐘後,響應終於回來並設置爲$rootScope.user_info

您的代碼存在的問題是3可能發生在2之後;它完全依賴於HTTP請求。這就是爲什麼有時而不是所有時間都有問題(因爲HTTP所花的時間是可變的)。你不想要它依賴於任何東西,你想保證2發生3


你可以做你的控制器和鏈中的HTTP請求關閉它,像這樣(注:.successdeprecated):

$http 
    .get('/api/v1/employees/'+$rootScope.current_user_id) 
    .then(function(response) { 
    $rootScope.user_info = response["data"]["user_info"]; 
    }) 
    .then(function() { 
    // $rootScope.user_info has been set 
    // your code here 
    }) 
; 

但是,這不會真的是一個不錯的辦法。您可能還想在其他地方訪問您的用戶,並且在任何地方重複此結構都不會非常乾燥。

所以你可以做的是你可以使用UI路由器的resolve功能。它基本上說:「在實現這些承諾解決之前不要實例化控制器」。所以你想說,「不要實例化控制器,直到HTTP請求獲得我的用戶數據解決」。

您的代碼將是這個樣子:

$stateProvider 
    .state('yourStateHere', { 
    url: '/yourUrlHere', 
    resolve: { 
     getUser: function($http, $rootScope) { 
     $http 
      .get('/api/v1/employees/' + $rootScope.current_user_id) 
      .then(function(response) { 
      $rootScope.user_info = response["data"]["user_info"]; 
      }) 
     ; 
     } 
    }, 
    controller: 'ControllerName' 
    }) 
; 
+0

我在其他控制器的許多地方使用$ rootScope.user_info。所以,如果我解決了我的http回調,可以使用user_info? – user9392255

+0

'resolve'所做的只是延遲了控制器的實例化,所以您仍然可以在這些控制器中使用'$ rootScope.user_info'。 –