为什么我无法从控制器访问$ rootScope值?

时间:2014-07-23 17:23:21

标签: angularjs angularjs-scope

我在$rootScope中将变量设置为true。此变量名为loggedIn。 我创建了一个NavController来控制主菜单链接的显示,正如您所看到的,我正确地注入了$rootScope

appControllers.controller("NavController", function($rootScope, $scope) {

  console.log($rootScope); //We can see that loggedIn is true
  console.log($rootScope.loggedIn); //Outputs false 

  //Not working as expected
  if($rootScope.loggedIn === true){
    $scope.showHomeMenu = false;
    $scope.showGameMenu = true;
    $scope.currentHome = '/lobby';
  }
  else {
    $scope.showHomeMenu = true;
    $scope.showGameMenu = false;
    $scope.currentHome = '/login';
  }
});

奇怪的是,这不起作用,因为$rootScope.loggedIn被评估为false,即使它的值设置为true。这是我从控制台获得的输出。

Console output

正如您从$rootScope输出中看到的那样,loggedIn应为true。但它被评估为控制器中的false

我想我在做一些非常愚蠢的事情,但我无法弄明白为什么!!

修改2

@rvignacio指出了一些有趣的东西。我看到的对象$rootScope是扩展时对象的状态,而不是我调用log()时的状态。 (这是可以预测的......)

我想这个问题比我想象的更深!我必须挖掘才能找到错误!

修改

我在run()中设置了loggedIn。

app.config(function($routeProvider, $httpProvider) {
  $routeProvider.
  when('/', {
   ...
  }).
   ...
  });


  var interceptor = ['$rootScope', '$q',
    function(scope, $q) {

      function success(response) {
        return response;
      }

      function error(response) {
        var status = response.status;

        if (status == 401) {
          var deferred = $q.defer();
          var req = {
            config: response.config,
            deferred: deferred
          };
          scope.$broadcast('event:loginRequired');
          return deferred.promise;
        }
        // otherwise
        return $q.reject(response);

      }

      return function(promise) {
        return promise.then(success, error);
      };

    }
  ];
  $httpProvider.responseInterceptors.push(interceptor);
}).run(['$rootScope', '$http', '$location',
  function(scope, $http, $location) {

    /**
     * Holds page you were on when 401 occured.
     * This is good because, for example:
     *  User goes to protected content page, for example in a bookmark.
     *  401 triggers relog, this will send them back where they wanted to go in the first place.
     */
    scope.pageWhen401 = "";
    scope.loggedIn = false;

    scope.logout = function() {
      $http.get('backend/logout.php').success(function(data) {
        scope.loggedIn = false;
        scope.$broadcast('event:doCheckLogin');
      }).error(function(data) {
        scope.$broadcast('event:doCheckLogin');
      });
    };

    scope.$on('event:loginRequired', function() {    
      //Only redirect if we aren't on restricted pages
      if ($location.path() == "/signup" ||
        $location.path() == "/login" ||
        $location.path() == "/contact" ||
        $location.path() == "/about")
        return;

      //go to the login page
      $location.path('/login').replace();
    });

    /**
     * On 'event:loginConfirmed', return to the page.
     */
    scope.$on('event:loginConfirmed', function() {
      //*********************
      //THIS IS WHERE I SET loggedIN
      //*********************
      scope.loggedIn = true;
      console.log("Login confirmed!");
      $location.path('/lobby').replace();
    });

    /**
     * On 'logoutRequest' invoke logout on the server and broadcast 'event:loginRequired'.
     */
    scope.$on('event:logoutRequest', function() {
      scope.logout();
    });

    scope.$on("$locationChangeSuccess", function(event) {
      //event.preventDefault();
      ping();
    });

    scope.$on('event:doCheckLogin', function() {
      ping();
    });

    /**
     * Ping server to figure out if user is already logged in.
     */
    function ping() {
      $http.get('backend/checksession.php').success(function() {
        scope.$broadcast('event:loginConfirmed');
      }); //If it fails the interceptor will automatically redirect you.
    }

    //Finally check the logged in state on every load
    ping();
  }
]);

1 个答案:

答案 0 :(得分:1)

你们是对的。我使用异步调用将loggedIn设置为true,所以这完全是时间问题。

欢迎来到异性恋世界亲爱的我。

$watch - ing loggedIn解决了这个问题。

appControllers.controller("NavController", function($rootScope, $scope) {
    $scope.showHomeMenu = true;
    $scope.showGameMenu = false;
    $scope.currentHome = '/login';

  //ADDED
  $rootScope.$watch('loggedIn', function(){
  console.log($rootScope.loggedIn);  
  if($rootScope.loggedIn === true){
    $scope.showHomeMenu = false;
    $scope.showGameMenu = true;
    $scope.currentHome = '/lobby';
  }
  else {
    $scope.showHomeMenu = true;
    $scope.showGameMenu = false;
    $scope.currentHome = '/login';
  }});
});

此外,我更改了在我的代码中将loggedIn设置为false的位置,以提高性能并在注销时消除可见延迟。现在一切都很快。