Angular 角度变量未定义

Angular 角度变量未定义,angular,typescript,Angular,Typescript,我编写了以下代码: authentication.service.ts export class AuthenticationService { private readonly ACCESS_TOKEN = 'ACCESS_TOKEN'; private readonly REFRESH_TOKEN = 'REFRESH_TOKEN'; private loggedUser: string; public userId : number; public user : Us

我编写了以下代码:

authentication.service.ts

export class AuthenticationService {
  private readonly ACCESS_TOKEN = 'ACCESS_TOKEN';
  private readonly REFRESH_TOKEN = 'REFRESH_TOKEN';
  private loggedUser: string;
  public userId : number; 
  public user : User; 
  private API_URL= environment.API_URL;


  constructor(private http: HttpClient, private router:Router, private userService : UserService) {}

  login(username: string, password:string): Observable<boolean> {
    return this.http.post<any>(this.API_URL + 'token/', { username: username, password: password })
      .pipe(
        tap(tokens => this.doLoginUser(username, tokens)),
        mapTo(true),
        catchError(error => {
          return of(false);
        }));
  }

  logout() {
    this.doLogoutUser();
  }

  decodeJwt(token){
    let decoded = jwt_decode(token);
    this.userId = decoded.user_id; 
  }

  isLoggedIn() {
    return !!this.getAccessToken();
  }

  isStaff() {
    return this.user.is_staff; 
  }

  refreshToken() {
    return this.http.post<any>(this.API_URL + "token/refresh/", {
      'refresh': this.getRefreshToken()
    }).pipe(
      tap((tokens: Tokens) => {
      this.storeJwtToken(tokens.access);
      }),
      mapTo(true), 
      catchError(error => {
        this.doLogoutUser(); 
        this.router.navigate(["/login"])
        return of(false); 
      }
      )
      );
  }

  getAccessToken() {
    return localStorage.getItem(this.ACCESS_TOKEN);
  }

  getUserData(){
    this.userService.getUser(this.userId).subscribe(data => {
      this.user = data.results[0]
      console.log(this.user)
    })
  }

  private doLoginUser(username: string, tokens: Tokens) {
    this.loggedUser = username;
    this.storeTokens(tokens);
    this.decodeJwt(tokens.access); 
    this.getUserData(); 
  }

  private doLogoutUser() {
    this.loggedUser = null;
    this.removeTokens();
  }

  private getRefreshToken() {
    return localStorage.getItem(this.REFRESH_TOKEN);
  }

  private storeJwtToken(accessToken: string) {
    localStorage.setItem(this.ACCESS_TOKEN, accessToken);
  }

  private storeTokens(tokens: Tokens) {
    localStorage.setItem(this.ACCESS_TOKEN, tokens.access);
    localStorage.setItem(this.REFRESH_TOKEN, tokens.refresh);
  }

  private removeTokens() {
    localStorage.removeItem(this.ACCESS_TOKEN);
    localStorage.removeItem(this.REFRESH_TOKEN);
  }
} 
export class NavbarComponent implements OnInit {
  constructor(public authService : AuthenticationService, private router : Router) { 
  }

  ngOnInit(): void {
    console.log(this.authService.isStaff())
  }

  logOut(){
    this.authService.logout() 
    this.router.navigate(['/login']);
  }
}
export class UserService {
  private API_URL= environment.API_URL;

  constructor(private http : HttpClient) { }

  getUsers(page:number=1){
    return this.http.get<any>(this.API_URL + 'users/', {
      params: new HttpParams().set("page", page.toString())
    });
  }

  register(data:User) {
    return this.http.post<any>(this.API_URL + 'users/', data)
  }

  getUser(id : number){
    return this.http.get<any>(this.API_URL + 'users/' + id.toString())
  }
}
user.service.ts

export class AuthenticationService {
  private readonly ACCESS_TOKEN = 'ACCESS_TOKEN';
  private readonly REFRESH_TOKEN = 'REFRESH_TOKEN';
  private loggedUser: string;
  public userId : number; 
  public user : User; 
  private API_URL= environment.API_URL;


  constructor(private http: HttpClient, private router:Router, private userService : UserService) {}

  login(username: string, password:string): Observable<boolean> {
    return this.http.post<any>(this.API_URL + 'token/', { username: username, password: password })
      .pipe(
        tap(tokens => this.doLoginUser(username, tokens)),
        mapTo(true),
        catchError(error => {
          return of(false);
        }));
  }

  logout() {
    this.doLogoutUser();
  }

  decodeJwt(token){
    let decoded = jwt_decode(token);
    this.userId = decoded.user_id; 
  }

  isLoggedIn() {
    return !!this.getAccessToken();
  }

  isStaff() {
    return this.user.is_staff; 
  }

  refreshToken() {
    return this.http.post<any>(this.API_URL + "token/refresh/", {
      'refresh': this.getRefreshToken()
    }).pipe(
      tap((tokens: Tokens) => {
      this.storeJwtToken(tokens.access);
      }),
      mapTo(true), 
      catchError(error => {
        this.doLogoutUser(); 
        this.router.navigate(["/login"])
        return of(false); 
      }
      )
      );
  }

  getAccessToken() {
    return localStorage.getItem(this.ACCESS_TOKEN);
  }

  getUserData(){
    this.userService.getUser(this.userId).subscribe(data => {
      this.user = data.results[0]
      console.log(this.user)
    })
  }

  private doLoginUser(username: string, tokens: Tokens) {
    this.loggedUser = username;
    this.storeTokens(tokens);
    this.decodeJwt(tokens.access); 
    this.getUserData(); 
  }

  private doLogoutUser() {
    this.loggedUser = null;
    this.removeTokens();
  }

  private getRefreshToken() {
    return localStorage.getItem(this.REFRESH_TOKEN);
  }

  private storeJwtToken(accessToken: string) {
    localStorage.setItem(this.ACCESS_TOKEN, accessToken);
  }

  private storeTokens(tokens: Tokens) {
    localStorage.setItem(this.ACCESS_TOKEN, tokens.access);
    localStorage.setItem(this.REFRESH_TOKEN, tokens.refresh);
  }

  private removeTokens() {
    localStorage.removeItem(this.ACCESS_TOKEN);
    localStorage.removeItem(this.REFRESH_TOKEN);
  }
} 
export class NavbarComponent implements OnInit {
  constructor(public authService : AuthenticationService, private router : Router) { 
  }

  ngOnInit(): void {
    console.log(this.authService.isStaff())
  }

  logOut(){
    this.authService.logout() 
    this.router.navigate(['/login']);
  }
}
export class UserService {
  private API_URL= environment.API_URL;

  constructor(private http : HttpClient) { }

  getUsers(page:number=1){
    return this.http.get<any>(this.API_URL + 'users/', {
      params: new HttpParams().set("page", page.toString())
    });
  }

  register(data:User) {
    return this.http.post<any>(this.API_URL + 'users/', data)
  }

  getUser(id : number){
    return this.http.get<any>(this.API_URL + 'users/' + id.toString())
  }
}
导出类用户服务{
私有API_URL=environment.API_URL;
构造函数(私有http:HttpClient){}
getUsers(页码:number=1){
返回this.http.get(this.API_URL+'users/'{
params:new-HttpParams().set(“page”,page.toString())
});
}
寄存器(数据:用户){
返回this.http.post(this.API_URL+'users/',数据)
}
getUser(id:number){
返回this.http.get(this.API_URL+'users/'+id.toString())
}
}
登录
getUser
-函数时调用,但当我检查控制台时,navbar构造函数给出错误,即
authentication.service.ts
中的
isStaff
-函数中的
this.user
未定义。用户端点工作正常,因为当我在subscribe函数中记录
data.results[0]
的值时,它会显示用户的数据


如何解决此问题?

不太确定,但此代码对我来说毫无意义:
this.authService.isStaff()

您似乎正在调用一个服务,该服务将检查此.user,无论它是否已定义,这不是一个好主意

相反,您不应该使用该服务获取用户,然后将
this.user
传递到导航栏组件中,然后直接检查是否
this.user.is_staff


只是一个想法。

这是因为变量
未定义

export class AuthenticationService {
  private readonly ACCESS_TOKEN = 'ACCESS_TOKEN';
  private readonly REFRESH_TOKEN = 'REFRESH_TOKEN';
  private loggedUser: string;
  public userId : number;
  public user : User;   =======> UNDEFINED
  private API_URL= environment.API_URL;
只有在
登录
服务和
获取用户数据
完成后,才会定义this.user。在那之前没有。但是我认为
Navbar
组件甚至在服务调用完成之前就已经初始化了

在上面的代码中,我没有看到对
AuthenticationService.login
函数的任何调用。所以我有两个选择

选项1->在用户登录之前,不要显示
navbar
组件


选项2->用户登录后,从
AuthenticationService
抛出事件。在访问this.user之前,在
navbar
组件中订阅该事件。

我认为这是由于同步性。函数在值发出之前被调用。尝试转换逻辑相关的观察值
toPromise()
,然后调用私有函数。您可能还想加入一些
async/await
。@jamesmalred您有这样的例子吗?从您的代码中不清楚babar是在用户登录之后还是之前创建的。试着创建一个stackblitz演示。这不是意味着当我需要用户变量时,我需要反复调用它吗?我不是一个专家,但我认为一般来说,你登录,然后将登录信息保存到内存或会话存储或本地存储,所以你不必每次更改页面时都重新登录。将用户信息保存到对象后,应该能够将该对象传递到导航栏中。但是你的导航栏本身不应该调用你的服务。即使用户登录到控制台,仍然会抛出相同的错误。表示变量仍然未定义您是否表示只有在完成对login和this.userService.getUser的调用后才初始化navbar组件?如果是,您是否检查了从this.userService.getUser收到的响应?看起来您正在将其分配给此.user。