确保订户更新的顺序

时间:2015-07-29 12:43:15

标签: javascript functional-programming reactive-programming rxjs reactive-extensions-js

是否有办法确保订阅者如何更新订单?

我有一个热的观察者,我的第一个订阅者做了一些同步工作来更新变量,然后我的下一个订阅者必须初始化一个服务(只有一次!),并且只有在确保设置该变量之后! / p>

它看起来像这样:

import App from './App'

var appSource = App.init() // gets the hot observable

// our second subscriber
appSource.take(1).subscribe(() => {
  // take 1 to only run this once
  nextService.init()
})

App.init看起来像这样:

...
init() {
  var source = this.createObservable() // returns a hot interval observable that fetches a resource every few minutes

  // first subscriber, updates the `myVar` every few minutes
  source.subscribe((data) => this.myVar = data)

  return source
}
...

目前有效,但我不确定它是否始终遵循100%的订单。

修改

正如我所听到的,订阅者将被调用FIFO。所以订单有点保证。

1 个答案:

答案 0 :(得分:2)

我不知道RxJS是否明确保证按订阅顺序调用观察者。但是,正如你所说,它通常有效。

但是,您可以考虑对实际工作流建模,而不是依赖隐式观察者顺序。

听起来您需要知道应用程序何时初始化,以便您可以采取进一步措施。而不是依赖App.init的内部运作知识,App可以为此公开API:

一个(非Rx方式)是让呼叫者向init提供回叫:

//...
init(callback) {
  var source = this.createObservable() // returns a hot interval observable that fetches a resource every few minutes

  // first subscriber, updates the `myVar` every few minutes
  source.subscribe((data) => {
    this.myVar = data;
    if (callback) {
        callback();
        callback = undefined;
    }
  })

  return source
}

// elsewhere
App.init(() => nextService.init());

另一个选项而不是回调只是让init返回一个Promise,表示你的决心(或你发出信号的Rx.AsyncSubject)初始化完成后。

另一种选择,但需要一些重构,就是将this.myVar建模为可观察的数据。即:

init() {
    this.myVar = this.createObservable().replay(1);
    this.myVar.connect();
    // returns an observable that signals when we are initialized
    return this.myVar.first();
}

// elsewhere, you end up with this pattern...
const servicesToInit = [ App, service1, service2, service3 ];
Observable
    .of(servicesToInit)
    .concatMap(s => Rx.Observable.defer(() => s.init()))
    .toArray()
    .subscribe(results => {
        // all initializations complete
        // results is an array containing the value returned by each service's init observable
    });

现在,任何想要使用myVar的东西总是需要以某种方式订阅它以获取当前和/或未来的值。他们永远不能同时询问当前的价值。