2015-12-01 62 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'。 –