【问题标题】:rxjs using promise only once on subscriberxjs 在订阅时只使用一次承诺
【发布时间】:2016-06-26 09:54:36
【问题描述】:

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

首先我尝试了这个:

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

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

然后我尝试了:

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

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

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

【问题讨论】:

  • 所以你只希望它被调用一次,但是如果它在它已经完成之后被调用你想让它做什么呢?

标签: javascript promise rxjs


【解决方案1】:

.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)

我们这里有一个流,它以一个虚拟对象开始,以使事情滚动,然后是一个由刷新事件组成的流。这些中的每一个都被投影到一个新的可观察对象中,该可观察对象是从您的 getMyPromise 方法的新调用创建的,并且整个事物都被扁平化为单个流。最后,我们保留了 shareReplay 逻辑,因此我们只在需要时才真正进行调用。

需要注意的是,只有在源始终至少有一个订阅者时,这才能正常工作(在所有其他订阅者都被释放后,第一个订阅将再次运行承诺,并将接收先前缓存的值和结果它导致运行的承诺)。

【讨论】:

  • 这很棒。谢谢!有没有办法将您的解决方案与回调的重新加载机制结合起来? --> 一个事件被触发,我可以对 rxjs-callback-method 执行调用。当此方法被调用时,它会在 _this.getMyPromise() 上执行一个新调用,并且每个订阅者都会收到有关新数据的通知?我知道这远远超出了我最初的要求,但这只是我想到的下一件事......
  • TBH,我有点困惑 fromPromise 不像其他所有东西一样接受回调。
【解决方案2】:

这是一个不需要在源头始终使用一个简单助手的至少一个订阅者的答案:

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

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

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

【讨论】:

  • 我的回答中的警告仅适用于第二个要求。如何调整这种方法来解决这个问题?将 _p 设置回 null 将导致新订阅者获得新的承诺,但是您将如何安排将新承诺的结果推送给现有订阅者?
猜你喜欢
  • 2019-05-10
  • 2019-08-31
  • 1970-01-01
  • 2017-09-21
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 2017-12-12
  • 1970-01-01
相关资源
最近更新 更多