发布于 2016-05-03 02:20:20
何时使用Subject.prototype.asObservable()
这样做的目的是为了防止主体的“观察者端”从API中泄漏出来。当你不希望人们能够“下一步”进入最终的可观察对象时,基本上是为了防止泄漏的抽象。
示例
(注意:这确实不是您应该如何将这样的数据源转换为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()
不像大多数可观察对象那样懒惰,它将立即创建底层数据源SomeWeirdDataSource
(以及一些副作用)。这也意味着如果你retry
或者repeat
得到的观察值,它不会像你想的那样工作。
最好将数据源的创建封装在可观察对象中,如下所示:
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的现有操作符在可观察对象的顶部进行组合。
发布于 2019-08-19 18:46:15
Subject
既可以充当observer
,也可以充当observable
.
一个Obervable
有两个方法。
只要你订阅了一个observable
,,你就会得到一个observer
,上面有next、error和complete方法。
您需要隐藏该序列,因为您不希望流源在每个组件中都是公开可用的。你可以参考@BenLesh
的例子,了解同样的情况。
附言:当我第一次使用反应式Javascript时,我还不能理解asObservable
.因为我必须确保我清楚地理解了基础知识,然后选择asObservable
.:)
发布于 2021-09-08 12:42:34
除了this answer之外,我还想提一下,在我看来,这取决于所使用的语言。
对于像JavaScript这样的无类型(或弱类型)语言,通过像asObservable()
方法那样创建委托对象来对调用者隐藏源对象可能是有意义的。不过,如果你仔细想想,它不会阻止调用者执行observable.source.next(...)
。因此,这种技术不能防止主题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,所以在某些情况下,您可能仍然需要创建一个委托。但我的观点是,与使用普通的JavaScript相比,这些情况下的空间要小得多,而且在大多数情况下,您可能不需要使用这种方法。
https://stackoverflow.com/questions/36986548
复制相似问题