我想知道有什么用asObservable
:
根据文档:
隐藏源序列身份的可观察序列。
但是为什么你需要隐藏序列呢?
这样做的目的是防止从 API 中泄露 Subject 的“观察者端”。基本上是为了防止当您不希望人们能够“下一个”进入结果的 observable 时出现泄漏的抽象。
(注意:这真的不是你应该如何将这样的数据源变成一个 Observable,而是你应该使用new Observable
构造函数,见下文)。
const myAPI = {
getData: () => {
const subject = new Subject();
const source = new SomeWeirdDataSource();
source.onMessage = (data) => subject.next({ type: 'message', data });
source.onOtherMessage = (data) => subject.next({ type: 'othermessage', data });
return subject.asObservable();
}
};
myAPI.getData()
现在,当有人从他们无法next
重视结果中获得可观察的结果时:
const result = myAPI.getData();
result.next('LOL hax!'); // throws an error because `next` doesn't exist
new Observable()
不过,您通常应该使用在上面的示例中,我们可能正在创建一些我们不打算这样做的东西。一方面,getData()
它不像大多数 observables 那样懒惰,它会立即创建底层数据源SomeWeirdDataSource
(可能还有一些副作用)。这也意味着,如果您retry
或repeat
由此产生的 observable,它不会像您想象的那样工作。
最好将数据源的创建封装在 observable 中,如下所示:
const myAPI = {
getData: () => return new Observable(subscriber => {
const source = new SomeWeirdDataSource();
source.onMessage = (data) => subscriber.next({ type: 'message', data });
source.onOtherMessage = (data) => subscriber.next({ type: 'othermessage', data });
return () => {
// Even better, now we can tear down the data source for cancellation!
source.destroy();
};
});
}
使用上面的代码,任何行为,包括使其“不懒惰”都可以使用 RxJS 现有的操作符在可观察对象之上组成。
ASubject
可以同时充当 anobserver
和 an observable
。
AnObervable
有 2 种方法。
每当您订阅anobservable
时,您都会得到一个observer
which 上有next、error和complete方法。
您需要隐藏序列,因为您不希望流源在每个组件中都公开可用。你可以参考@BenLesh
的例子,同样的。
PS:当我第一次接触 Reactive Javascript 时,我无法理解asObservable
。因为我必须确保我清楚地了解基础知识,然后再选择asObservable
. :)
除了这个答案,我还要提到,在我看来,这取决于所使用的语言。
对于像JavaScript这样的无类型(或弱类型)语言,通过像asObservable()
方法一样创建委托对象来向调用者隐藏源对象可能是有意义的。尽管如果您考虑一下,它不会阻止调用者执行observable.source.next(...)
. 所以这种技术并不能防止 Subject API 泄漏,但它确实使它对调用者更加隐藏。
另一方面,对于像TypeScript这样的强类型语言,该方法asObservable()
似乎没有多大意义(如果有的话)。静态类型语言通过简单地利用类型系统(例如接口)来解决 API 泄漏问题。例如,如果您的getData()
方法被定义为返回,Observable<T>
那么您可以安全地返回原始Subject
的 ,如果尝试调用getData().next()
它,调用者将收到编译错误。
想想这个修改过的例子:
let myAPI: { getData: () => Observable<any> }
myAPI = {
getData: () => {
const subject = new Subject()
// ... stuff ...
return subject
}
}
myAPI.getData().next() // <--- error TS2339: Property 'next' does not exist on type 'Observable<any>'
当然,由于它最终都会编译为JavaScript,因此可能仍然存在您想要创建委托的情况。但我的观点是,这些情况的空间比使用 vanilla JavaScript时要小得多,并且可能在大多数情况下您不需要该方法。