如果其他observable在RxJS中有数据,如何忽略一个observable?

时间:2017-04-01 00:38:44

标签: javascript rxjs observable

我有两个observable,一个从浏览器 localstorage 接收数据,另一个从数据库 WebAPI

  1. 我想订阅它们,所以如果 localstorage 中的observable有数据,请不要启动该数据来从数据库获取数据。
  2. 如果 localstorage 中的观察者没有 数据,调用 ajax 调用以从 WebAPI 获取数据。
  3. 在下面的示例中,我应该只获得20, 40, 60, 80, 100因为第一个observable有数据。第二个observable没有运行,因为第一个observable开始发送数据。

    enter image description here

2 个答案:

答案 0 :(得分:2)

您可以使用skipWhile并检查数据并返回true或false。

observableObject.skipWhile((data)=> {
      if(data){
          return false;
      }
});

答案 1 :(得分:2)

本地存储可观察性需要某种方式来表示没有数据。如果它只是“挂起”并且永远不会完成,那么您可以使用计时器来完成它:

// Use .amb() instead of .race() if your rxjs version is old
const timer = Observable.timer(1000).ignoreElements();
const lsObservable2 = Observable.race(lsObservable, timer);

这将启动一个计时器,如果本地存储observable不产生1s内的值,它将结束流。

如果没有数据,本地存储可观察性将自行完成,那么您可以按原样使用它:

const lsObservable2 = lsObservable;

此时,我们真的很想使用defaultIfEmpty,因为它具有您想要的语义。不幸的是,它只支持默认的标量值,而是想要产生不同的可观察流。因此,让我们编写自己的defaultIfEmpty版本,使用Observable.defer生成一个新流。我们使用defer以便每次有人订阅时,我们都可以创建一个新的闭包变量(hasValue)并监视源observable是否为此订阅生成一个值

Observable.prototype.defaultObservableIfEmpty = function(defaultObservable) {
    const source = this;
    return Observable.defer(() => {
        let hasValue = false;
        // create a deferred observable that will evaluate to
        // defaultObservable if we have not seen any values, or
        // empty observable if we have seen any values.
        const next = Observable.defer(() => hasValue ? Observable.empty() : defaultObservable);

        // now use do() to set hasValue to true if we see a value from
        // the source observable
        const sourceSetsValue = source.do(v => hasValue = true);

        // now we can can just concat this sourceSetsValue
        // with out "next" observable.  When the first observable
        // finishes, it will subscribe to "next", which will then
        // either produce the defaultObservable or an empty observable
        return sourceSetsValue.concat(next);
    });
}

接下来,假设您已经设置了db Observable,在实际订阅之前不发出ajax调用。这是重要的一步。您可以再次使用defer

之类的内容
const dbObservable = Observable.defer(() => makeDbCall());

然后我们可以像你这样使用你的新运算符:

const data = lsObservable2.defaultObservableIfEmpty(dbObservable);

因此,您的应用程序代码如下所示(一旦您将新运算符添加到库中):

const timer = Observable.timer(1000).ignoreElements();
const lsObservable2 = Observable.race(lsObservable, timer);
const dbObservable = Observable.defer(() => makeDbCall());
const data = lsObservable2.defaultObservableIfEmpty(dbObservable);