Sco*_*ott 9 javascript angularjs
我是棱角分明的新手,我很难找到问题的根源.
我正在编写单页应用程序,正在处理身份验证部分.我有一个名为"sessionService"的服务,我希望能够在整个应用程序中使用该服务来确定用户是否已登录.如果我做这样的事情很简单:
...service('sessionService', function(...) {
/*...snip...*/
this.isLoggedIn = function() {
return this.authenticated;
};
});
Run Code Online (Sandbox Code Playgroud)
"经过身份验证"的地方只是服务的私人空间.但是,如果我刷新页面,则会崩溃.所以,我的想法是做这样的事情:
/*...snip...*/
this.isLoggedIn = function() {
var deferred = $q.defer()
, self = this
;
function handleLoggedInStatus(status) {
if (status) {
self.authenticated = true;
deferred.resolve();
}
else {
deferred.reject();
}
}
if (this.authenticated === null) {
$http.get('/user')
.success(function(response) {
handleLoggedInStatus(response.success);
});
}
else {
handleLoggedInStatus(this.authenticated);
}
return deferred.promise;
};
Run Code Online (Sandbox Code Playgroud)
然后在我的控制器中我会做这样的事情:
$scope.isLoggedIn = sessionService.isLoggedIn;
Run Code Online (Sandbox Code Playgroud)
在我的模板中,我会这样做:
...data-ng-show="isLoggedIn()"
Run Code Online (Sandbox Code Playgroud)
但是,这样做会导致以下错误:
10 $digest() iterations reached. Aborting!
Run Code Online (Sandbox Code Playgroud)
我尝试了几种不同的方法来引用sessionService.isLoggedIn函数,例如:
$scope.isLoggedIn = sessionService.isLoggedIn();
$scope.isLoggedIn = sessionService.isLoggedIn.bind(sessionService)();
$scope.isLoggedIn = function() { return sessionService.isLoggedIn() }
Run Code Online (Sandbox Code Playgroud)
但他们要么不起作用,要么只是给了我同样的错误.
基本上,我只是希望能够返回一个承诺,告诉我用户是否已登录.如果我们不知道他们是否已登录(如页面刷新后),则承诺将在以后解决一个ajax请求.如果我们已经知道(就像整个单页应用程序中的正常导航一样)那么承诺将立即得到解决.然后我想在我的视图中使用它,以便显示/隐藏某些内容,例如注销链接或查看帐户页面.
我究竟做错了什么?
你正在解决你的承诺,但没有价值 - 因此,$scope
解决时的承诺价值undefined
是假的,因此你ng-show
不会触发.
看来你正在寻找更像这样的东西:
在服务中:
function handleLoggedInStatus(status) {
if (status) {
self.authenticated = true;
}
deferred.resolve(status); // always resolve, even if with falsy value
}
if (this.authenticated === null) {
$http.get('/user')
.success(function(response) {
handleLoggedInStatus(response.success);
})
.error(function(data) {
deferred.reject(data.errorMsg); // reject if there was an error
});
} else {
handleLoggedInStatus(this.authenticated);
}
Run Code Online (Sandbox Code Playgroud)
在控制器中:
$scope.loggedIn = sessionService.isLoggedIn();
Run Code Online (Sandbox Code Playgroud)
在HTML中:
<div ng-show='loggedIn'>...</div>
Run Code Online (Sandbox Code Playgroud)
这是一个JSFiddle演示解决延迟与truthy值和绑定到$scope
.
请注意,您无法将函数本身绑定到作用域
$scope.loggedIn = sessionService.isLoggedIn
Run Code Online (Sandbox Code Playgroud)
并在视图中调用该函数
<div ng-show="loggedIn()">...</div>
Run Code Online (Sandbox Code Playgroud)
因为该函数每个摘要周期返回一个不同的 promise(这就是你得到'10摘要周期'错误的原因).但是,您可以确保额外的调用sessionService.isLoggedIn
返回相同的承诺而不是创建新的承诺,因为您可以then
多次调用promise(事实上这是promises的好处之一):
deferred = null;
isLoggedIn: function() {
if (!deferred) {
deferred = $q.defer();
$http.get('/user')
.success(function(response) {
deferred.resolve(response.success); // resolve if true or false
})
.error(function(data) {
deferred.reject(data.errorMsg); // reject if there was an error
});
}
return deferred.promise;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以摆脱this.authenticated
布尔值,因为你不需要在函数调用中跟踪以前登录的用户(因为promise会为你做这个).
然而,虽然这消除了摘要周期错误,但您仍然无法从视图中调用该函数 - 我怀疑Angular将返回值(promise本身)视为truthy值,而不是绑定到promise的已解析值.这是一个不起作用的例子 ; 注意div
即使承诺正在解决,也会显示false
.
要使用deferred.reject
指示用户在没有认证的,在原来的服务,你会想要做的事更多类似这样的控制器,但我认为,resolve
与荷兰国际集团false
是清洁:
sessionService.isLoggedIn()
.then(function() {
$scope.loggedIn = true; // resolved
}).then(function() {
$scope.loggedIn = false; // rejected
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10945 次 |
最近记录: |