如何跟踪 angularJS 控制器中的当前用户?
How to keep track of current user in angularJS controllers?
工厂/服务:
angular.module('phoenix-template')
.factory('User', ['$http', function($http){
function current(){
$http.get('http://localhost:4000/api/current_user').then(function(res){
return res.data;
})
}
this.currentUser = current();
}]);
})();
控制器:
(function(){
'use strict';
angular.module('phoenix-template')
.controller('NavCtrl', ['$scope','User', function($scope, User){
$scope.currentUser = User.currentUser;
$scope.$watch( 'currentUser', function () {
User.currentUser = $scope.currentUser;
});
}]);
})();
我在后端跟踪当前用户,但我想跨控制器在 angular 中跟踪我的当前用户用于显示等目的。
但是,我显然做错了..
提示、帮助,非常感谢。
您可以使用 $cookies 来存储用户数据,例如用户名、令牌等。您可以在此处阅读文档 https://docs.angularjs.org/api/ngCookies/service/$cookies
从后端服务获取用户对象后,使用 $cookies 存储它,然后在需要的地方获取该值。
例如,您重新加载页面,然后在 app.run
阶段,从 $cookie 获取该用户对象并存储在某个服务或 $rootScope
我在一个示例应用程序中做了一些事情,我不记得它是否 100% OK 但它会有所帮助
(function () {
'use strict';
var app = angular.module('app');
app.run(runFunction);
runFunction.$inject = ['$rootScope', '$state', '$cookies', '$window'];
/* @ngInject */
function runFunction($rootScope, $state, $cookies, $window) {
//// Set User
var user = $cookie.get('user')
/*
Or you can do something
if ($window.sessionStorage["user"]) {
$rootScope.user = JSON.parse($window.sessionStorage["user"]);
}
*/
if (user) {
$rootScope.user = JSON.parse(user);
} else {
$rootScope.user = {
id: 0,
username: 'Anonymous'
};
}
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var isAuthenticate = toState.authenticate;
if (isAuthenticate && !$rootScope.user.token) {
event.preventDefault();
alert('Please login first');
$state.go('login');
});
}
})();
我相信您感到困惑的地方是 factory
和 service
在 angular 中并不相同。
- 每次注入都会创建一个工厂
- 服务是单例,在 angular 应用程序的生命周期内只创建一次。
在这种情况下,该服务是注入控制器的最佳选择。第一个访问它的人将从您的服务器具体化用户数据。使用该服务的其余控制器将使用相同的服务实例,因此没有为每个控制器访问服务器的开销。
这是代码。该服务使用函数检索用户,但将结果保存到本地字段,这样它只会被调用一次。然后您的控制器可以调用该函数来检索它(如果您添加一些检查逻辑,甚至可以直接访问该字段)。
(function(){
angular.module('phoenix-template')
.service('ngUserService', ['$http', function($http){
var me = this;
function getUser(callback) {
// if the user has already been retrieved then do not do it again, just return the retrieved instance
if(me.currentUser)
calback(me.currentUser);
// retrieve the currentUser and set it as a property on the service
$http.get('http://localhost:4000/api/current_user').then(function(res){
// set the result to a field on the service
me.currentUser = res.data;
// call the callback with the retrieved user
callback(me.currentUser);
});
}
return {getUser:getUser}
}]);
})();
控制器代码
(function(){
'use strict';
angular.module('phoenix-template')
.controller('NavCtrl', ['$scope','ngUserService', function($scope, ngUserService){
// call to get the user and set it to your scope variable
ngUserService.getUser(function(user){$scope.currentUser = user;});
}]);
})();
我看到我们没有讨论将数据保存在浏览器内存中,例如 localStorage 和 Cookies。
我明白了,你想以某种方式从后端观察状态。
这是可能的,但为了性能,最好不要在所有摘要周期中都这样做。
我建议设置时间间隔——不要太小以免网络过载,也不要太大以保持当前的信息跟踪。
Here 是关于 Angular 区间问题的答案。我认为这会有所帮助。
这个解决方案可以这样实现:
.controller('NavCtrl', function($scope, User,$interval){
$scope.loadCurrentUser = function (){
$scope.currentUser = User.currentUser;
};
//Put in interval, first trigger after 10 seconds
$interval(function(){
$scope.loadCurrentUser();
}, 10000);
//invoke initialy
$scope.loadCurrentUser();
});
我的代码删除了依赖注入。我建议使用名为 ng-annotate.
的自动解决依赖注入的工具
工厂/服务:
angular.module('phoenix-template')
.factory('User', ['$http', function($http){
function current(){
$http.get('http://localhost:4000/api/current_user').then(function(res){
return res.data;
})
}
this.currentUser = current();
}]);
})();
控制器:
(function(){
'use strict';
angular.module('phoenix-template')
.controller('NavCtrl', ['$scope','User', function($scope, User){
$scope.currentUser = User.currentUser;
$scope.$watch( 'currentUser', function () {
User.currentUser = $scope.currentUser;
});
}]);
})();
我在后端跟踪当前用户,但我想跨控制器在 angular 中跟踪我的当前用户用于显示等目的。
但是,我显然做错了..
提示、帮助,非常感谢。
您可以使用 $cookies 来存储用户数据,例如用户名、令牌等。您可以在此处阅读文档 https://docs.angularjs.org/api/ngCookies/service/$cookies
从后端服务获取用户对象后,使用 $cookies 存储它,然后在需要的地方获取该值。
例如,您重新加载页面,然后在 app.run
阶段,从 $cookie 获取该用户对象并存储在某个服务或 $rootScope
我在一个示例应用程序中做了一些事情,我不记得它是否 100% OK 但它会有所帮助
(function () {
'use strict';
var app = angular.module('app');
app.run(runFunction);
runFunction.$inject = ['$rootScope', '$state', '$cookies', '$window'];
/* @ngInject */
function runFunction($rootScope, $state, $cookies, $window) {
//// Set User
var user = $cookie.get('user')
/*
Or you can do something
if ($window.sessionStorage["user"]) {
$rootScope.user = JSON.parse($window.sessionStorage["user"]);
}
*/
if (user) {
$rootScope.user = JSON.parse(user);
} else {
$rootScope.user = {
id: 0,
username: 'Anonymous'
};
}
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var isAuthenticate = toState.authenticate;
if (isAuthenticate && !$rootScope.user.token) {
event.preventDefault();
alert('Please login first');
$state.go('login');
});
}
})();
我相信您感到困惑的地方是 factory
和 service
在 angular 中并不相同。
- 每次注入都会创建一个工厂
- 服务是单例,在 angular 应用程序的生命周期内只创建一次。
在这种情况下,该服务是注入控制器的最佳选择。第一个访问它的人将从您的服务器具体化用户数据。使用该服务的其余控制器将使用相同的服务实例,因此没有为每个控制器访问服务器的开销。
这是代码。该服务使用函数检索用户,但将结果保存到本地字段,这样它只会被调用一次。然后您的控制器可以调用该函数来检索它(如果您添加一些检查逻辑,甚至可以直接访问该字段)。
(function(){
angular.module('phoenix-template')
.service('ngUserService', ['$http', function($http){
var me = this;
function getUser(callback) {
// if the user has already been retrieved then do not do it again, just return the retrieved instance
if(me.currentUser)
calback(me.currentUser);
// retrieve the currentUser and set it as a property on the service
$http.get('http://localhost:4000/api/current_user').then(function(res){
// set the result to a field on the service
me.currentUser = res.data;
// call the callback with the retrieved user
callback(me.currentUser);
});
}
return {getUser:getUser}
}]);
})();
控制器代码
(function(){
'use strict';
angular.module('phoenix-template')
.controller('NavCtrl', ['$scope','ngUserService', function($scope, ngUserService){
// call to get the user and set it to your scope variable
ngUserService.getUser(function(user){$scope.currentUser = user;});
}]);
})();
我看到我们没有讨论将数据保存在浏览器内存中,例如 localStorage 和 Cookies。 我明白了,你想以某种方式从后端观察状态。 这是可能的,但为了性能,最好不要在所有摘要周期中都这样做。 我建议设置时间间隔——不要太小以免网络过载,也不要太大以保持当前的信息跟踪。
Here 是关于 Angular 区间问题的答案。我认为这会有所帮助。 这个解决方案可以这样实现:
.controller('NavCtrl', function($scope, User,$interval){
$scope.loadCurrentUser = function (){
$scope.currentUser = User.currentUser;
};
//Put in interval, first trigger after 10 seconds
$interval(function(){
$scope.loadCurrentUser();
}, 10000);
//invoke initialy
$scope.loadCurrentUser();
});
我的代码删除了依赖注入。我建议使用名为 ng-annotate.
的自动解决依赖注入的工具