下面是我的代码,相关部分加粗:
授权.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._id
是undefined
,而我试图对其调用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)
,则给出了一个空对象。不知道为什么。
AFAIK,由于Javascript是单线程的,当线程在while循环中旋转时,http回调将得不到CPU时间来处理响应。
似乎正在发生的是,您的身份验证内容正在被异步检查(这是有意义的,因为它必须执行HTTP调用,而这不是即时的)
因此,在运行脚本时,auth.getCurrentUser()
的结果,即CurrentUser
对象,没有填充您试图访问的数据,因为它是在这一行写入的:
angular.copy(data, currentUser);
它确实在一个异步块内。所以现在的情况是,_id
可能还不是CurrentUser
上的属性,所以实际上是在Undefined
上调用ToString()
。
您的解决方案可能是使用回调或承诺。如果您是auth.factory.js
的作者,那么您可能会考虑做的是在GetCurrentUser
中同步返回对象,而不是返回一个承诺或回调,当HTTP请求完成时,它就会实现。
编辑:这也是脚本中的console.dir
不会返回任何内容的原因,因为在它运行时,它不会填充任何数据。