【问题标题】:Does Subject.complete() unsubscribe all listeners?Subject.complete() 是否取消订阅所有听众?
【发布时间】:2017-03-20 01:50:01
【问题描述】:

我用这个方法构建了一个简单的确认对话服务(Angular 2):

confirm(body?: string, title?: string): Subject<void> {
    this.confirmation = new Subject<void>();
    // ... show dialog here... "are you sure?"
    return this.confirmation;
}

_onYesClicked() {
  // ... closing the dialog
  this.confirmation.next();
  this.confirmation.complete();
} 

_onNoClicked() {
  // ... closing the dialog
  this.confirmation.complete();
}

用法:

confirmationService.confirm().subscribe(() => alert("CONFIRMED"));

如果有人使用该服务,他会返回一个 Subject(它是一个 Observable)并且可以“订阅()”它。单击“是”时会调用订阅,因此会给出确认...

这是正确的方法吗?更重要的是……会打电话给

this.confirmation.complete();

取消订阅已订阅的侦听器,从而防止任何延迟引用(内存泄漏)?

【问题讨论】:

  • 我编辑了标题,因为complete() 方法不是 Obervable 接口的一部分。

标签: angular rxjs observable


【解决方案1】:

如果您想确保它会删除所有观察者,您可以在 https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L91 中自行检查。它在所有观察者上调用complete()(观察者通常只是实现Observer interface 的哑对象),然后设置this.observers.length = 0;。所以答案是肯定的。

您的方法是有效的,它与 Angular2 对 EventEmitter 的常规做法基本相同。您可以改进的一件事是在公开Subjects 时开始使用asObservable()。这将隐藏您在下面使用Subject 并仅返回常规 Observable 的事实。这样您就不会让您的用户意外(或由于误解)尝试在您的 Subject 上调用 next()complete()error()

关于内存泄漏,这必须由 RxJS 处理,所以你不必担心,如果有问题,作者可能会在你之前注意到它。

也看看这个:Observable vs Subject and asObservable

【讨论】:

  • 当用户单击 No 时,我也会调用 error() 而不是 complete()。或者我会使用 Promise 而不是 Observable。顺便说一句,ng-bootstrap modals 就是这样做的。
  • 呵呵呵呵……真是天才,只看源头——这让我确信没有保留任何参考资料。对“asObservable()”也有很好的建议 - 谢谢!
  • @JBNizet 我认为单击“否”并不一定意味着错误,但我猜这是 OP 的问题,而不是我的问题。
  • @JBNizet 无意冒犯,但这只是个坏建议。调用 error() 来指示有效的用户流不是好的设计。代码错误旨在表明技术上出现了问题,而不是表明用户在对话中说不。这样想:如果用户在询问“你想炸毁世界吗?”的对话框上单击“否”,我会说这不是错误。简而言之,错误是为可能导致程序中断的未处理代码流设计的,而不是指示在有效用例中接下来要采用哪个逻辑分支。
  • 哇,多么棒的答案!因为这个,我今天学到了很多:)
猜你喜欢
  • 1970-01-01
  • 2021-09-30
  • 1970-01-01
  • 2019-01-31
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多