rxjs只在订阅时使用promise一次

Dom*_*nic 11 javascript promise rxjs

我想rxjs第一次使用,但我有点被困'因为它的行为与我想要的完全不同:在我的场景中,我想从一个承诺中创建一个observable.但我希望承诺只被调用一次(不是每次订阅),我希望它不会在创建时被调用(将调用推迟到第一个订阅).

首先我尝试了这个:

var source = Rx.Observable.fromPromise(_this.getMyPromise())
Run Code Online (Sandbox Code Playgroud)

这会导致getMyPromise在创建时调用该函数.这并不令人满意,因为当时我不知道是否真的会使用这个来源.

然后我尝试了:

var source = Rx.Observable.defer(function() { return _this.getMyPromise() })
Run Code Online (Sandbox Code Playgroud)

getMyPromise每次对源进行新订阅时都会调用该函数.这会对Web服务器进行太多不必要的调用.该Rx.Observable.create功能似乎有同样的问题.

那剩下什么或者我错过了什么?

Mat*_*ell 6

.shareReplay() 这样做,例如:

var source = Rx.Observable.defer(function() { return _this.getMyPromise() }).shareReplay();
Run Code Online (Sandbox Code Playgroud)

如果您正在使用rxjs5,则需要阅读:RxJS5中的shareReplay(1)模式

在回答下面的评论时,我可以想到对上述逻辑的一个相当直接的扩展,它会做你想要的,但它有一个警告.假设您要用来触发"刷新"的事件在流s $中表示,那么您可以执行以下操作:

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

我们这里有一个以虚拟对象开头的流来开始滚动,然后是一个由刷新事件组成的流.这些中的每一个都被投射到一个新的observable中,该observable是通过对getMyPromise方法的全新调用创建的,并且整个过程被展平为一个单独的流.最后,我们保留shareReplay逻辑,这样我们才能实际调用.

需要注意的是,只有在始终至少有一个订阅者的情况下才能正常工作(在所有其他订阅之后的第一个订阅将再次运行promise,并且将同时接收先前缓存的值和承诺的结果导致运行).