从订阅 BehaviorSubject 获取未定义的值返回为 Observable

Getting undefined values from subscribing to BehaviorSubject returned as Observable

所以我想把当前登录用户的名字放在header中。现在,我可以通过登录来完成,但是如果我刷新页面,我将丢失我发现在 SPA 中正常行为的值。(虽然数据仍在本地存储中)所以我创建了一个函数将再次获取本地存储中当前登录的用户并将其存储在我的身份验证服务中。我在 header 组件的 ngOnInit() 中执行此操作。但是,我得到未定义的值。据我了解,它应该 return 自从我订阅它以来的最后一个值。此外,我是 re-assigning 在从服务中获取它之前的值。

授权服务

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

import { CurrentUserInterface } from '../interfaces/current-user.interface';

@Injectable()
export class AuthenticationService {
private rootUrl = 'testapi.com';

private currentUser = new BehaviorSubject<CurrentUserInterface>();
private isAuthorized: BehaviorSubject<boolean> = new BehaviorSubject(false);

constructor(private http: HttpClient) { }

setCurrentUser(): void {
    if(localStorage.getItem("currentUser")) {
        this.currentUser.next(JSON.parse(localStorage.getItem("currentUser")));
        this.isAuthorized.next(true);
    }
    else {
        this.isAuthorized.next(false);
    }
    console.log(this.currentUser.value); **//HAS VALUES**
}

getCurrentUser(): Observable<CurrentUserInterface> {
    return this.currentUser.asObservable();
}

checkAuth(): Observable<boolean> {
    return this.isAuthorized.asObservable();
}
}

header分量

    import { Component, OnInit } from '@angular/core';
    import { Router } from '@angular/router';

    import { Observable } from 'rxjs/Observable';

    import { AuthenticationService } from '../_shared/services/authentication.service';

    import { CurrentUserInterface } from '../_shared/interfaces/current-user.interface';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  private currentUser = new Observable<CurrentUserInterface>;
  private isAuthorized: Observable<boolean> = false;

  constructor(private router: Router,
      private authenticationService: AuthenticationService) { }

  ngOnInit() {
      this.authenticationService.setCurrentUser();
      this.isAuthorized = this.authenticationService.checkAuth()
      .subscribe(
          isAuthorized => {
              this.isAuthorized = isAuthorized;
          },
          error => {
              console.log(error);
          }
      );

      this.currentUser = this.authenticationService.getCurrentUser()
      .subscribe(
          currentUser => {
              this.currentUser = currentUser;
          },
          error => {
              console.log(error);
          }
      );

      console.log(this.currentUser.value); **// UNDEFINED**
      console.log(this.isAuthorized.value); **// UNDEFINED**
   }

   logout() {
          this.authenticationService.logout();
          this.router.navigate(['../login'], { relativeTo: this.route });
   }

}

这是您的 HeaderComponent ngOnInit() 的固定版本。请注意,对 HTTP 服务的调用是异步的。命令流仅在 onNext、onError 或 onComplete 处理程序内部继续。在服务对可观察对象进行任何调用之前执行订阅调用之后的任何代码。在您的情况下,例如 this.currentUser.value 是未定义的,因为您将 this.currentUser 分配给了一个可观察对象。可观察对象没有 .value 属性。您可以通过严格输入变量来完全解决这些问题。

ngOnInit() {
      this.authenticationService.setCurrentUser();
      // removed assignment to this.isAuthorized
      this.authenticationService.checkAuth()
      .subscribe(
          isAuthorized => {
              this.isAuthorized = isAuthorized;
          },
          error => {
              console.log(error);
          }
      );

      // removed assignment to this.currentUser
      this.authenticationService.getCurrentUser()
      .subscribe(
          currentUser => {
              this.currentUser = currentUser;
              // moved console.log calls into onNext handler. They should not be undefined any more unless the .value properties do really not exist. 
              console.log(this.currentUser.value); 
              console.log(this.isAuthorized.value);
          },
          error => {
              console.log(error);
          }
      );    

   }

您正在将可观察对象的结果分配给可观察对象本身。这就是你所拥有的:

private currentUser = new Observable<CurrentUserInterface>;

然后

this.currentUser = this.authenticationService.getCurrentUser() //<====== here
      .subscribe(
          currentUser => {
              this.currentUser = currentUser; //<========= and here
          },
          error => {
              console.log(error);
          }
      );

而且,console.log 甚至会在您收到回复之前 运行。

试试这个:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { Observable } from 'rxjs/Observable';

import { AuthenticationService } from '../_shared/services/authentication.service';

import { CurrentUserInterface } from '../_shared/interfaces/current-user.interface';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  private currentUser: CurrentUserInterface;
  private isAuthorized: Observable<boolean> = false;

  constructor(private router: Router,
      private authenticationService: AuthenticationService) { }

  ngOnInit() {
      this.authenticationService.setCurrentUser();
      this.isAuthorized = this.authenticationService.checkAuth()
      .subscribe(
          isAuthorized => {
              this.isAuthorized = isAuthorized;
          },
          error => {
              console.log(error);
          }
      );

      this.authenticationService.getCurrentUser()
      .subscribe(
          currentUser => {
              this.currentUser = currentUser;
              console.log(this.currentUser);  //<====== console.log here
          },
          error => {
              console.log(error);
          }
      );
   }

   logout() {
          this.authenticationService.logout();
          this.router.navigate(['../login'], { relativeTo: this.route });
   }

}