在Angular服务中取消订阅无限可观察量的最佳方法是什么

时间:2017-12-26 21:40:37

标签: angular rxjs

在我们的Angular websocket服务中,为了告诉后端我们还在听,我们必须发送一种保持活动信号。

以下是我们的进展方式:

@Injectable()
export class WebsocketService {
  private ws: CustomWebSocket;

  constructor() {
    this.ws = new CustomWebSocket('ws://localhost');
    this.ws.onOpened(() => {
      console.info('WS connected');
      this.keepAlive();
    });
  }

  public keepAlive() {
    Observable.interval(10000).subscribe((tick: number) => this.ws.send('keep-alive'));
  }
}

1 /此服务注入我们的主app.module.ts。我们是否必须手动取消订阅间隔,或者允许这种无限可观测序列是否安全?

2 /作为一般性问题,如果我们必须取消订阅,由于订阅是在服务范围内,这样做的正确方法是什么?我们没有ngOnDestroy生命周期钩子,所以如何正确地做到这一点?

2 个答案:

答案 0 :(得分:3)

  

我们是否必须手动取消订阅时间间隔,或者允许这种无限可观察序列是安全的?

通常情况下,如果服务意味着应用程序的整个生命周期都存在,那么您就不必费心了,因为浏览器会为您清理。但是,有一些事情需要考虑:

  • 如果您的应用仅在较大的应用中加载,则不再适用。
  • 如果您将应用更改为仅在某个子组件上提供服务,则必须了解该服务的实现细节,并记住将其调整为自行清理以避免内存泄漏。

遵循最少惊喜的原则,服务应该在销毁后自行清理,所以我绝对会建议这样做。

  

我们没有ngOnDestroy生命周期钩子,所以如何正确地做到这一点?

这是一个流行的声明,但这是错误的。 ngOnDestroy也被称为服务。直接从the docs

  

销毁指令,管道或服务时调用的生命周期钩子。

所以你绝对可以这样做:

@Injectable()
export class WebsocketService implements OnDestroy {
  private ws: CustomWebSocket;
  private destroy$ = new Subject();

  constructor() {
    this.ws = new CustomWebSocket('ws://localhost');
    this.ws.onOpened(() => {
      console.info('WS connected');
      this.keepAlive();
    });
  }

  public keepAlive() {
    Observable.interval(10000)
      .takeUntil(this.destroy$)
      .subscribe((tick: number) => this.ws.send('keep-alive'));
  }

  public ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

答案 1 :(得分:0)

该服务的问题在于,您没有取消订阅的销毁方法,并且确实需要取消订阅,只有http请求是自动关闭的(http服务会为您执行此操作)。

我希望你的WebsocketService向你的主应用程序组件返回一个冷的observable。

在主应用组件中为您的observable创建占位符 IE:ngUnsubscribe:Subject = new Subject();

从您的服务订阅您的o​​bservable。 IE:WebsocketService.keepAlive()。takeUntil(this.ngUnsubscribe).subscribe();

在主应用程序组件的onDestroy事件中,我将调用this.ngUnsubscribe.next(); this.ngUnsubscribe.complete();