我正在开展个人Angular项目。仍在尝试学习并从AngularJS转移到Angular:)
这是我的代码:
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { LoginService } from './login.service';
@Injectable()
export class LoggedInGuard implements CanActivate {
constructor(
private _router: Router,
private _loginService: LoginService
) {
}
isLoggedIn() {
let token = localStorage.getItem('token');
if ( token ) {
this._loginService.isLoggedIn(token)
.subscribe(v => {
return v.status == 'ok';
});
} else {
return false;
}
};
canActivate() {
console.log(this.isLoggedIn());
if (this.isLoggedIn()) {
return true;
} else {
this._router.navigate(['/login']);
return false;
};
}
}
但我的问题是:
this.
保留在console.log(this.isLoggedIn());
上,那么"未定义"打印出来。[ts] Cannot find name 'isLoggedIn'. Did you mean the instance member 'this.isLoggedIn'?
上有以下消息,并在控制台上Uncaught (in promise): ReferenceError: isLoggedIn is not defined
isLoggedIn()
在我调用的其他文件中使用没有问题。答案 0 :(得分:2)
您在方法上未定义的原因:
isLoggedIn() {
let token = localStorage.getItem('token');
if ( token ) {
this._loginService.isLoggedIn(token)
.subscribe(v => {
return v.status == 'ok';
});
} else {
return false;
}
};
是因为订阅this._loginService.isLoggedIn(token)
是异步的,并且不会立即返回。所以方法isLoggedIn()
完成执行并在有响应之前返回。
你可以做什么而我做的是让你的_loginService
维护一个其他组件可以读取和使用的局部变量,或者一个可以同步检查令牌以确保它有效的功能。如果存在令牌,则用户已登录,您可以从中执行的操作是检查令牌以确保其未过期。这可以通过几种不同的方式完成。如果您使用angular2-jwt
库来帮助处理您的JWT令牌,那么_loginService
中的方法可能会如下所示:
authenticated() {
// Check if there's an unexpired JWT
return tokenNotExpired();
}
如果您没有使用angular-jwt
库来帮助管理JWT令牌,您可以这样做:
isTokenValid(){
let token = localStorage.getItem('token');
let decodedToken = window.atob(token.split('.')[1]);
if((decodedToken.exp * 1000) < Date.now()){
return false;
}
return true;
}
希望有所帮助。
答案 1 :(得分:1)
这可能没有资格作为答案,但我没有足够的声誉点发表评论 - 所以大家,请原谅我:)
我认为你无法从订阅中返回一个值,因为它是异步调用..
相反,应返回isLoggedIn()方法,如下所示:
isLoggedIn() {
let token = localStorage.getItem('token');
if ( token ) {
return this._loginService.isLoggedIn(token)
.subscribe(v => {
return v.status == 'ok';
});
} else {
return false;
}
};
请注意,此处的更改是:return this._loginService.isLoggedIn(token)...
希望这会有所帮助。
编辑: 忽略我上面的答案......那仍然行不通:(对不起...... 发生了什么,你正在调用isLoggedIn()来执行异步调用(即一个将在后台继续执行并稍后返回的调用)。这就是为什么你得到一个未定义的&#39;。我要做的是遵循上面的Tyler建议,并有一个局部变量,在其中存储返回的值并在以后使用或者你可以将回调传递给isLoggedIn()方法 - 这个回调将在异步时被调用通话已完成。见下文:
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { LoginService } from './login.service';
@Injectable()
export class LoggedInGuard implements CanActivate {
constructor(
private _router: Router,
private _loginService: LoginService
) {
}
isLoggedIn(callback: (v) => void) {
let token = localStorage.getItem('token');
if ( token ) {
this._loginService.isLoggedIn(token)
.subscribe(v => {
callback(v)
});
}
};
canActivate() {
this.isLoggedIn((v) => { // this here is your callback function which will get invoked once async call is done
if(v.status == 'ok' {
// do something...
return true;
} else {
// do something
this._router.navigate(['/login']);
}
});
}
}