rxjs 在订阅时只使用一次承诺

rxjs using promise only once on subscribe

我想第一次使用 rxjs 但有点卡住了,因为它的行为与我想要的不完全一样:在我的场景中,我想从承诺中创建一个可观察对象。但我希望承诺只被调用一次(不是在每个订阅上)并且我希望它不在创建时被调用(将调用推迟到第一个订阅)。

首先我尝试了这个:

var source = Rx.Observable.fromPromise(_this.getMyPromise())

这导致在创建时立即调用 getMyPromise 函数。这个不太满意,因为那个时候不知道源码是不是真的会用

然后我尝试了:

var source = Rx.Observable.defer(function() { return _this.getMyPromise() })

每次对源进行新订阅时都会调用 getMyPromise 函数。这对网络服务器造成了太多不必要的调用。 Rx.Observable.create 函数似乎有同样的问题。

那么我还剩下什么或缺少什么?

.shareReplay() 这样做,例如:

var source = Rx.Observable.defer(function() { return _this.getMyPromise() }).shareReplay();

如果您使用的是 rxjs5,您需要阅读:

在回答您在下面的评论时,我可以想到对上述逻辑进行相当简单的扩展,它可以满足您的要求,但有一个警告。假设您想用来触发 "refresh" 的事件在流 s$ 中表示,那么您可以执行以下操作:

var source = Rx.Observable.of({}).concat(s$)
    .flatMapLatest(function() {
        return Rx.Observable.defer(function() {
            return _this.getMyPromise()
        })
    })
    .shareReplay(1)

我们这里有一个流,以一个虚拟对象开始,让事情滚动,然后是一个由您的刷新事件组成的流。这些中的每一个都被投影到一个新的可观察对象中,该观察对象是通过重新调用您的 getMyPromise 方法创建的,并且整个事情被扁平化为一个单一的流。最后,我们保留了 shareReplay 逻辑,所以我们只在应该调用的时候才实际调用。

需要注意的是,这只有在始终至少有一个订阅者订阅源的情况下才能正常工作(处理所有其他订阅者后的第一个订阅者将再次 运行 承诺,并将收到之前的两个 -缓存值及其对 运行).

的承诺结果

这里有一个答案,它不需要使用简单的帮助程序始终在源头至少有一个订阅者:

var _p = null;
var once = function() { return _p || (_p = _this.getMyPromise());

var source = Rx.Observable.defer(once);

或者,如果您使用的是 lodash,您可以 _.memoize 您的 getMyPromise 并自动获取它。