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

时间:2018-01-15 16:06:51

标签: angular typescript rxjs angular5

所以我想把当前登录用户的名字放在标题中。现在,我可以通过登录来实现,但是如果我刷新页面,我将丢失我发现的值是SPA中的正常行为。(数据仍然在本地存储中)所以我创建了一个函数将再次获取本地存储中当前登录的用户并将其存储在我的身份验证服务中。我在头部组件的ngOnInit()中执行此操作。但是,我得到了未定义的值。根据我的理解,它应该返回自订阅以来的最后一个值。此外,在我从服务中获取值之前,我首先重新分配这些值。

身份验证服务

$('label').hide();

$('input').on('keyup', function(e){
  $(this).prev().show();
});

标题组件

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();
}
}

2 个答案:

答案 0 :(得分:2)

您正在为observable本身分配一个可观察的结果。这就是你所拥有的:

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 });
   }

}

答案 1 :(得分:1)

这是HeaderComponent ngOnInit()的固定版本。请注意,对HTTP服务的调用是异步的。命令流仅在onNext,onError或onComplete处理程序内继续。在服务对observable进行任何调用之前,会在订阅调用之后直接执行任何代码。在您的情况下,例如this.currentUser.value是未定义的,因为您已将this.currentUser分配给observable。一个observable没有.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);
          }
      );    

   }