Subject.complete() 是不是取消订阅所有听众?
Posted
技术标签:
【中文标题】Subject.complete() 是不是取消订阅所有听众?【英文标题】: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 接口的一部分。
【参考方案1】:
如果您想确保它会删除所有观察者,您可以在 https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L91 中自行检查。它在所有观察者上调用complete()
(观察者通常只是实现Observer interface 的哑对象),然后设置this.observers.length = 0;
。所以答案是肯定的。
您的方法是有效的,它与 Angular2 对 EventEmitter
的常规做法基本相同。您可以改进的一件事是在公开Subject
s 时开始使用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() 来指示有效的用户流不是好的设计。代码错误旨在表明技术上出现了问题,而不是表明用户在对话中说不。这样想:如果用户在询问“你想炸毁世界吗?”的对话框上单击“否”,我会说这不是错误。简而言之,错误是为可能导致程序中断的未处理代码流设计的,而不是指示在有效用例中接下来要采用哪个逻辑分支。 哇,多么棒的答案!因为这个,我今天学到了很多:)以上是关于Subject.complete() 是不是取消订阅所有听众?的主要内容,如果未能解决你的问题,请参考以下文章