BehaviorSubject未发出值

时间:2019-01-23 06:30:05

标签: angular angular7 rxjs6 behaviorsubject

在Angular 7应用程序中,我有一个登录服务和一个管理员,该服务跟踪该人是否已登录。由于某种原因,只能看到来自true方法的初始login值。在服务中,我有这个:

private admin = new BehaviorSubject(false);
admin$ = this.admin.asObservable();

login(user: string, pwd: string): Observable<ILoginData> {
    sessionStorage.removeItem('admin');

    const coded = btoa(`${user}:${pwd}`);
    const headers = new HttpHeaders({
        'Authorization': `Basic ${coded}`,
    });

    return this.http
        .post<ILoginData>(`${this.baseUrl}/login`, null, {headers: headers})
        .pipe(
            tap(x => {
                sessionStorage.setItem('admin', JSON.stringify(x.admin));

                this.admin.next(x.admin);
            })
        )
}

logout(): void {
    sessionStorage.removeItem('admin');
    this.admin.next(false);
}

然后app.component.ts订阅:

private subscription: Subscription;

ngOnInit(): void {
    this.subscription = this.producerService.admin$.subscribe(x => {
        console.info(`Admin being set to ${x}`);
        this.showAdminSection = x;
    });
}

ngOnDestroy(): void {
    if (this.subscription) {
        this.subscription.unsubscribe();
    }
}

我看到的是登录订阅时会调用一个值,但是当我调用logout()方法时,即使我正在发送false更新,消息仍然是从不打印到控制台,说它已设置为false。就像只发出第一个值,然后由于某种原因而关闭订阅。

我不确定为什么false似乎没有被发送/接收。

1 个答案:

答案 0 :(得分:0)

在从可观察值获取最新值之前调用ngOnDestroy不一定是正确的。

这取决于执行操作所需的逻辑或时间。对于您而言,logout需要更多时间,并且在完成之前,将调用ngOnDestroy并且您的订阅被销毁。

例如,请考虑此处stackblitz上的代码。如果您在 test.service.ts 文件中看到,我创建了两个函数,如下所示:

...
  nextValueDelayed(value: boolean) {
    setTimeout(() => {
      this._test.next(value);
    });
  }

  nextValue(value: boolean) {
    this._test.next(value);
  }
...

现在,从 app.component.ts 中,我称呼如下:

...
  reverse() {
    this.visible = !this.visible;
    this._testService.nextValue(this.visible);
  }

  reverseDelayed() {
    this.visible = !this.visible;
    this._testService.nextValueDelayed(this.visible);
  }
...

这两个函数都通过按钮调用,visible负责创建和销毁HelloComponent app.component.html

<hello name="{{ name }}" *ngIf="visible"></hello>
<button (click)="reverse()">Reverse</button>
<button (click)="reverseDelayed()">Reverse Delayed</button>

现在,HelloComponent正在订阅和确认值,并取消订阅destroy,如下所示: hello.component.ts

...
ngOnInit(){
    this.sub = this._testService.test$.subscribe(value=>{
      console.log(value);
    })
  }

  ngOnDestroy(){
    this.sub.unsubscribe();
  }
...

现在,尝试单击ReverseReverse Delayed按钮,您会看到,当您单击Reverse时,它将打印所有值。但是,当您单击Reverse Delayed时,组件将在获得最新值之前被销毁,因为我们已经使用setTimeout来增加一些延迟。