假设我有两个类,您可以在其中观察一些 observables。
第一个例子,公共(public)主题:
class EventsPub {
public readonly onEnd = new Subject<void>();
}
第二个例子,使用私有(private)主题和注册方法:
class EventsPriv {
private readonly endEvent = new Subject<void>();
public onEnd(cb: () => void): Subscription {
return this.endEvent.subscribe(cb);
}
}
第一个示例在某种程度上是不安全的,因为任何人都可以从类外部调用
eventsPub.endEvent.next()
并引入副作用,但是,与示例 2 相比,它允许使用管道,这是一个很大的优势,因为开发人员可以例如。仅使用 eventsPub.onEnd.pipe(first()).subscribe(cb)
注册第一个事件。第二个示例也允许一次性订阅,但需要更多代码和丑陋的取消订阅。
const subscription = eventsPriv.onEnd(() => {
// logic..
subscription.unsubscribe()
});
从您的 Angular 来看,哪种方式最好?或者也许有更好的解决方案?
最佳答案
这很大程度上取决于我的个人喜好,但我会这样做:
class EventsPriv {
private readonly endEvent = new Subject<void>();
get endEvent$(): Observable<void> {
return this.endEvent;
}
}
所以在类里面,我将使用
endEvent
,而我仍然可以使用它,例如。在带有 obj.endEvent$ | async
的模板中,从外面看,它的行为就像一个 Observable。请注意,实际上我返回的是
Subject
的相同实例。唯一限制外部世界将其与 obj.endEvent$.next()
一起使用的东西是 Typescript 的类型保护。如果我只使用 JavaScript 或者我将它的类型转换为 any
我可以调用 next
。这实际上是公开
Subject
s 而不是使用 asObservable()
运算符的推荐方式。你可以注意到在 RxJS 5 内部到处都使用了它。例如,如果你看 repeatWhen
synopsys:public repeatWhen(notifier: function(notifications: Observable): Observable): Observable
您可以看到
notifier
函数接收一个 Observable 作为参数(您也可以在此处的代码中看到它 https://github.com/ReactiveX/rxjs/blob/5.5.6/src/operators/repeatWhen.ts#L29 )。但是,如果您查看调用该函数的代码,您会发现它们实际上传递的是
Subject
而不是 Observable
: https://github.com/ReactiveX/rxjs/blob/5.5.6/src/operators/repeatWhen.ts#L114-L115 。这已经在 RxJS GitHub 页面上讨论过,其原因是性能和 Typescript 类型保护就足够了。您可以在这些讨论中阅读更多内容:
关于javascript - rxjs 科目应该在类里面公开吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48448364/