提问者:小点点

当运行块中存在无限循环时,工厂中的$HTTP成功回调不运行


下面是我的代码,相关部分加粗:

授权.js

 angular
      .module('mean-starter')
      .run(run);

    function run($rootScope, Auth, $state) {
      $rootScope.$on('$stateChangeStart', function(event, toState, toParams) {
        if (typeof toState.authenticate !== 'undefined') {
          var currentUser = Auth.getCurrentUser();
          while (!currentUser._id) {}
          var isAdmin = currentUser.role === 'admin';
          var isAuthorized = currentUser._id.toString() === toParams.id;
          if (!Auth.isLoggedIn()) {
            event.preventDefault();
            alert('Must be logged in to access this route.');
            $state.go('login');
          }
          else if (toState.authenticate.authorized) {
            if (!isAdmin && !isAuthorized) {
              event.preventDefault();
              alert('You are not authorized to access that route.');
            }
          }
          else if (toState.authenticate.isAdmin) {
            if (!isAdmin) {
              event.preventDefault();
              alert('You must be an admin to access this route.');
            }
          }
        }
      });
    }

auth.factory.js

angular
  .module('mean-starter')
  .factory('Auth', function($http, $state, $window, $cookies) {
    console.log('factory cb');
    var currentUser = {};
    if ($cookies.get('userId')) {
      console.log('userId');
      $http
        .get('/current-user')
        .success(function(data) {
          console.log('success');
          angular.copy(data, currentUser);
        })
        .error(function() {
          console.log('Problem getting the current user.');
        });
    }

    return {
      signup: function(user) {
        return $http.post('/users', user)
                  .success(function(data, status, headers, config) {
                    angular.copy(data, currentUser);
                    $cookies.put('userId', data._id);
                    $window.location.href = '/';
                  });
      },
      login: function(user) {
        return $http
                  .post('/login', user)
                  .success(function(data) {
                    angular.copy(data, currentUser);
                    $cookies.put('userId', data._id);
                    $window.location.href = '/';
                  });
      },
      logout: function() {
        $http
          .get('/logout')
          .success(function() {
            angular.copy({}, currentUser);
            $cookies.remove('userId');
            $window.location.href = '/';
          })
          .error(function() {
            console.log('Problem logging out.');
          });
      },
      getCurrentUser: function() {
        return currentUser;
      },
      isLoggedIn: function() {
        return !!currentUser._id;
      }
    };
  });

我的问题是,如果没有while循环,我会得到以下错误:

Cannot read property 'toString' of undefined

它指的是currentuser._idundefined,而我试图对其调用ToString。我的理解是,auth.getCurrentUser()最初返回对{}的引用。然后赋值语句将{}分配给CurrentUser,代码继续执行。当响应返回时,它应该更新{},因此应该“更新”CurrentUser,因为CurrentUser指向更新的对象。

如果这是真的,我的问题就可以理解了,因为它试图在响应返回之前执行currentuser._id.toString()。因此,我尝试将while循环放入其中,以暂停执行,直到响应返回。但是while循环正在无限地运行!响应是否应该最终返回,更新CurrentUser,当它返回时,!CurrentUser._ID应该是false,并且循环应该中断?

首先注销工厂CB。则userid将注销。到目前为止还不错。但随后无限循环启动,success永远无法注销。请求不是应该是异步的吗?while循环如何阻止它?这是怎么回事?

电话没有问题。如果没有while循环,它将命中success回调并记录success。此外,如果authorization.js中的Iconsole.dir(currentUser)给出了用户,但如果Iconsole.log(currentUser),则给出了一个空对象。不知道为什么。


共2个答案

匿名用户

AFAIK,由于Javascript是单线程的,当线程在while循环中旋转时,http回调将得不到CPU时间来处理响应。

匿名用户

似乎正在发生的是,您的身份验证内容正在被异步检查(这是有意义的,因为它必须执行HTTP调用,而这不是即时的)

因此,在运行脚本时,auth.getCurrentUser()的结果,即CurrentUser对象,没有填充您试图访问的数据,因为它是在这一行写入的:

angular.copy(data, currentUser);

它确实在一个异步块内。所以现在的情况是,_id可能还不是CurrentUser上的属性,所以实际上是在Undefined上调用ToString()

您的解决方案可能是使用回调或承诺。如果您是auth.factory.js的作者,那么您可能会考虑做的是在GetCurrentUser中同步返回对象,而不是返回一个承诺或回调,当HTTP请求完成时,它就会实现。

编辑:这也是脚本中的console.dir不会返回任何内容的原因,因为在它运行时,它不会填充任何数据。