我想第一次使用rxjs
,但我有点被卡住了,因为它的行为并不像我想要的那样:在我的场景中,我想创建一个可观察的一个承诺。但我希望承诺只被调用一次(不是每次订阅),我希望它不会在创建时被调用(将调用推迟到第一个订阅)。
首先我尝试了这个:
var source = Rx.Observable.fromPromise(_this.getMyPromise())
导致在创建时调用getMyPromise
函数。这并不令人满意,因为那时候我还不知道是否真的会使用这个来源。
然后我尝试了:
var source = Rx.Observable.defer(function() { return _this.getMyPromise() })
每次对源进行新订阅时都会调用getMyPromise
函数。这会对Web服务器进行太多不必要的调用。 Rx.Observable.create
函数似乎也有同样的问题。
那剩下的是什么,或者我错过了什么?
答案 0 :(得分:6)
.shareReplay()
这样做,例如:
var source = Rx.Observable.defer(function() { return _this.getMyPromise() }).shareReplay();
如果您使用的是rxjs5,则需要阅读:Pattern for shareReplay(1) in RxJS5
在回答下面的评论时,我可以想到对上述逻辑的一个相当直接的扩展,它会做你想要的,但它有一个警告。假设您要用来触发“刷新”的事件在流s $中表示,那么您可以执行以下操作:
var source = Rx.Observable.of({}).concat(s$)
.flatMapLatest(function() {
return Rx.Observable.defer(function() {
return _this.getMyPromise()
})
})
.shareReplay(1)
我们这里有一个以虚拟对象开头的流来开始滚动,然后是一个由刷新事件组成的流。这些中的每一个都被投射到一个新的observable中,该observable是通过对getMyPromise方法的全新调用创建的,并且整个过程被展平为单个流。最后,我们保留shareReplay逻辑,这样我们才能在应该的时候实际调用。
需要注意的是,只有在始终至少有一个订阅者来源时才能正常工作(在处置完所有其他订阅之后的第一个订阅将再次运行promise,并且将同时接收先前缓存的值和结果它导致的承诺)。
答案 1 :(得分:0)
以下是一个答案,使用简单的帮助程序始终不需要至少一个订阅者:
var _p = null;
var once = function() { return _p || (_p = _this.getMyPromise());
var source = Rx.Observable.defer(once);
或者如果你正在使用lodash,你可以_.memoize
getMyPromise
自动获取此内容。