AngularJS:将数据从控制器传递到应用程序配置
AngularJS: pass data from controller to app config
我对 Angular 很陌生。我在我的 Angular 应用程序中使用令牌身份验证。我使用 HTTP 拦截器来检查我的后端 returns 401,然后使用刷新令牌进行登录:
myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector) {
var sessionRecoverer = {
responseError: function(response) {
// Session has expired
if (response.status === 401) {
var $http = $injector.get('$http');
var deferred = $q.defer();
var $auth = $injector.get('$auth');
$auth.login({
refresh_token: ????,
grant_type: 'refresh_token',
event_client: 'client',
client_id: 'id'
});
// When the session recovered, make the same backend call again and chain the request
return deferred.promise.then(function() {
return $http(response.config);
});
}
return $q.reject(response);
}
};
return sessionRecoverer;
}]);
现在,refresh_token 来自我的登录控制器(从 api 后端提取)。所以控制器必须以某种方式将它传递给拦截器。问题是拦截器在配置块中,所以没有服务、值等——只有提供者。但是提供者不能注入到控制器中。那么有没有办法将数据从控制器传递到app.config?如果没有,是否有解决方法?注入器可以在 app.config 以外的任何地方吗?
是的,你可以像这样简单地做:
myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector, TokenFactory) {
var sessionRecoverer = {
responseError: function(response) {
// Session has expired
if (response.status === 401) {
var $http = $injector.get('$http');
var deferred = $q.defer();
var $auth = $injector.get('$auth');
$auth.login({
refresh_token: TokenFactory.getRefreshToken(),
grant_type: 'refresh_token',
event_client: 'client',
client_id: 'id'
});
// When the session recovered, make the same backend call again and chain the request
return deferred.promise.then(function() {
return $http(response.config);
});
}
return $q.reject(response);
}
};
return sessionRecoverer;
}]);
正如你所说,块配置只能注入提供者,但拦截器本身是一个工厂,因此你可以注入其他工厂,例如一个名为 TokenFactory 的工厂,它应该提供一个方法 return 需要时刷新令牌。
编辑
如果 refresh_token 是来自后端的东西,并且您想从登录控制器在 TokenFactory 中设置一个值,您可以执行类似这样的操作来实现您的工厂和控制器:
myapp.factory('TokenFactory',function(){
var currentRefreshToken;
return {
setRefreshToken: function(token){
currentRefreshToken = token;
},
getRefreshToken: function(){
return currentRefreshToken:
}
};
});
myapp.controller('MyLoginCtrl',function($scope,TokenFactory,$http){
$scope.login = function(){
$http.post('http://myapp.com/refreshtoken',$scope.credentials)
.then(TokenFactory.setRefreshToken)
.then(function(){ /* ... */})
.catch(function(err){ console.error(err) })
;
};
});
数据持久化
如果你想让你的代币持久化,你可以编写一个使用 LocalStorage HTML5 API
的工厂并在你的 TokenFactory
:
中使用它
myapp.factory('TokenFactory',function(LocalStorage){
// load the value from localstorage (hard disk) on app starts
var currentRefreshToken = LocalStorage.get('myapp.currentRefreshToken');
return {
setRefreshToken: function(token){
currentRefreshToken = token; // save value in RAM
LocalStorage.set('myapp.currentRefreshToken',token); // and sync the localstorage value
},
getRefreshToken: function(){
return currentRefreshToken; // quick access to the value from RAM
}
};
});
myapp.factory('LocalStorage',function($window) {
var localStorage = {};
localStorage.set = function(key, value) {
$window.localStorage[key] = value;
};
localStorage.get = function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
};
localStorage.setObject = function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
};
localStorage.getObject = function(key) {
return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? {} : JSON.parse($window.localStorage[key]);
};
localStorage.setArray = function(key, array){
if (!array.length) {
console.debug(array);
$window.localStorage[key] = '[]';
} else{
this.setObject(key, array);
}
};
localStorage.getArray = function(key){
return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? [] : JSON.parse($window.localStorage[key]);
};
localStorage.exportAsFile = function(key, fileName){
var data = [$window.localStorage[key]] || ['{}'];
var blob = new Blob(data,{type:'application/json;charset=utf-8'});
$window.saveAs(blob,fileName);
};
return localStorage;
});
我对 Angular 很陌生。我在我的 Angular 应用程序中使用令牌身份验证。我使用 HTTP 拦截器来检查我的后端 returns 401,然后使用刷新令牌进行登录:
myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector) {
var sessionRecoverer = {
responseError: function(response) {
// Session has expired
if (response.status === 401) {
var $http = $injector.get('$http');
var deferred = $q.defer();
var $auth = $injector.get('$auth');
$auth.login({
refresh_token: ????,
grant_type: 'refresh_token',
event_client: 'client',
client_id: 'id'
});
// When the session recovered, make the same backend call again and chain the request
return deferred.promise.then(function() {
return $http(response.config);
});
}
return $q.reject(response);
}
};
return sessionRecoverer;
}]);
现在,refresh_token 来自我的登录控制器(从 api 后端提取)。所以控制器必须以某种方式将它传递给拦截器。问题是拦截器在配置块中,所以没有服务、值等——只有提供者。但是提供者不能注入到控制器中。那么有没有办法将数据从控制器传递到app.config?如果没有,是否有解决方法?注入器可以在 app.config 以外的任何地方吗?
是的,你可以像这样简单地做:
myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector, TokenFactory) {
var sessionRecoverer = {
responseError: function(response) {
// Session has expired
if (response.status === 401) {
var $http = $injector.get('$http');
var deferred = $q.defer();
var $auth = $injector.get('$auth');
$auth.login({
refresh_token: TokenFactory.getRefreshToken(),
grant_type: 'refresh_token',
event_client: 'client',
client_id: 'id'
});
// When the session recovered, make the same backend call again and chain the request
return deferred.promise.then(function() {
return $http(response.config);
});
}
return $q.reject(response);
}
};
return sessionRecoverer;
}]);
正如你所说,块配置只能注入提供者,但拦截器本身是一个工厂,因此你可以注入其他工厂,例如一个名为 TokenFactory 的工厂,它应该提供一个方法 return 需要时刷新令牌。
编辑
如果 refresh_token 是来自后端的东西,并且您想从登录控制器在 TokenFactory 中设置一个值,您可以执行类似这样的操作来实现您的工厂和控制器:
myapp.factory('TokenFactory',function(){
var currentRefreshToken;
return {
setRefreshToken: function(token){
currentRefreshToken = token;
},
getRefreshToken: function(){
return currentRefreshToken:
}
};
});
myapp.controller('MyLoginCtrl',function($scope,TokenFactory,$http){
$scope.login = function(){
$http.post('http://myapp.com/refreshtoken',$scope.credentials)
.then(TokenFactory.setRefreshToken)
.then(function(){ /* ... */})
.catch(function(err){ console.error(err) })
;
};
});
数据持久化
如果你想让你的代币持久化,你可以编写一个使用 LocalStorage HTML5 API
的工厂并在你的 TokenFactory
:
myapp.factory('TokenFactory',function(LocalStorage){
// load the value from localstorage (hard disk) on app starts
var currentRefreshToken = LocalStorage.get('myapp.currentRefreshToken');
return {
setRefreshToken: function(token){
currentRefreshToken = token; // save value in RAM
LocalStorage.set('myapp.currentRefreshToken',token); // and sync the localstorage value
},
getRefreshToken: function(){
return currentRefreshToken; // quick access to the value from RAM
}
};
});
myapp.factory('LocalStorage',function($window) {
var localStorage = {};
localStorage.set = function(key, value) {
$window.localStorage[key] = value;
};
localStorage.get = function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
};
localStorage.setObject = function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
};
localStorage.getObject = function(key) {
return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? {} : JSON.parse($window.localStorage[key]);
};
localStorage.setArray = function(key, array){
if (!array.length) {
console.debug(array);
$window.localStorage[key] = '[]';
} else{
this.setObject(key, array);
}
};
localStorage.getArray = function(key){
return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? [] : JSON.parse($window.localStorage[key]);
};
localStorage.exportAsFile = function(key, fileName){
var data = [$window.localStorage[key]] || ['{}'];
var blob = new Blob(data,{type:'application/json;charset=utf-8'});
$window.saveAs(blob,fileName);
};
return localStorage;
});