【问题标题】:Subscribing to BehaviorSubject after reloading the dialog component重新加载对话框组件后订阅 BehaviorSubject
【发布时间】:2019-04-24 07:07:31
【问题描述】:

这是我已有的代码:

device.service.ts

import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs';


@Injectable({
  providedIn: 'root'
})
export class DeviceService {

  deviceList: any;

  private deviceListSource = new BehaviorSubject(this.deviceList);
  currentDeviceList = this.deviceListSource.asObservable();

  constructor(){}

  getDevices(): void {
    this.http.get<any>('https://........')
      .subscribe(data => {
        this.deviceListSource.next(data.data);
      }, error => console.log('Could not GET devices.'));
  }

我的对话框组件如下所示:

devices.component.ts

  ngOnInit() {

      this.deviceService.getDevices();
      this.deviceService.currentDeviceList.subscribe(data => {
      console.log(data)
    });
  }

这非常适合在多个组件之间共享一些值。当我关闭对话框(即devices.component.ts)并再次重新打开它而不重新加载整个页面时,console.log(data) 命令的执行次数与我已经打开/关闭对话框的次数一样多。因此,当我打开对话框时,它会订阅.next() 服务添加的所有值。但我希望对话框只订阅服务添加的最后一个值。

据我了解,BehaviorSubject 正是针对此用例的。有什么我错过的吗?还是有另一种(更好的)方法来实现这一目标?

【问题讨论】:

  • 终止订阅。

标签: angular behaviorsubject


【解决方案1】:

先前的订阅仍然保留流,因此您需要在销毁设备组件之前清除它。一种方法是:

devices.component.ts

 destroy$ = new Subject();

 ngOnInit() {
      this.deviceService.getDevices();
      this.deviceService.currentDeviceList
       .pipe(takeUntil(this.destroy$)) // takUntil from rxjs
       .subscribe(data => {
      console.log(data)
    });
  }

 ngOnDestroy(){
    this.destroy$.next();
    this.destroy$.complete(); // always call complete for guaranteed subscription removal
 }

【讨论】:

  • 为什么需要this.destroy$.complete()this.deviceService.currentDeviceList 将在 destroy$ 发出新值时停止。
  • 根据我的经验,我发现 GC 不会在 next 之后立即收集引用,因此调用 complete 将确保正确清理。
  • 好吧,也许吧。没有玩过这种类型的unsubscribe()。这确实非常有用,而不是检查所有订阅变量的存在然后执行 unsubscribe()。
【解决方案2】:

关闭对话框后终止订阅。

someSubscription: Subscription
ngOnInit() {
      this.deviceService.getDevices();
      this.someSubscription = this.deviceService.currentDeviceList.subscribe(data => {
      console.log(data)
    });
}


ngOnDestroy() {
    if (this.someSubscription) {
        this.someSubscription .unsubscribe();
    }
}

【讨论】:

  • 好的,这很好用。感谢你们对我的帮助!只是想了解到底发生了什么。当我重新打开对话框组件时,之前的对话框操作中还有一些其他订阅实例,对吗?
  • @HansZimmer 是的,没错!如果你不杀掉你之前的订阅,当你重新打开对话框时,ngOnInit() 会被调用并创建一个新的订阅。
  • 非常感谢!这对我来说不是很清楚
  • 能否请您解释一下为什么第一次执行 console.log(data) 会抛出“未定义”?
  • 是的,但没有值。更新了我的帖子。我想我已经明白了,谢谢。
猜你喜欢
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
相关资源
最近更新 更多