2017-04-01 62 views
2

我有两个observable,一个接收来自浏览器的数据localstorage,另一个是从数据库WebAPI如果其他可观察数据在RxJS中有数据,如何忽略所有可观察数据?

  1. 我想订阅他们因此,如果观察到从localStorage的有数据,不发起一个从数据库获取数据。
  2. 如果从localStorage的可观察没有任何 数据,调用AJAX调用的WebAPI获取数据。

在下面的例子中,我应该只得到20, 40, 60, 80, 100,因为第一个可观察数据有数据。第二个观测值没有运行,因为第一个观测值开始发射数据。

enter image description here

+0

您希望本地存储器observable发出多少个值?据推测,只有一个;在这种情况下,问题是这一个愚蠢的:http://stackoverflow.com/a/39200507/6680611 – cartant

+0

我想要在该问题中提到的那个观察值的所有值。他们是''20,40,60,80,100'''。 –

+0

您的大理石图并不代表上面提出的问题。在图中,两个流同时开始**,并且您已经声明底部流将被忽略。而在上面的问题中,您声明如果本地存储可观察数据有数据,则不会启动ajax可观察**。此外,您不定义“有数据”的含义。本地存储观测值是否完整?目前还不清楚你在问什么。 – cartant

回答

2

本地存储可观察性需要某种方式来表示没有数据。如果它只是“挂起”并无法完成,那么你可以使用一个定时器来完成它:

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

这将启动一个定时器,并在本地存储观察到不产生1秒之内的值,它会结束流。

如果您的本地存储观察到的将自行完成,如果没有数据,那么你可以把它当成是:

const lsObservable2 = lsObservable; 

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

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); 
2

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

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

这只适用于一个可观察项。问题中有两个观察点。 –

+0

你能否详细说明。 – Aravind

+0

你可以看看这个[问题](http://stackoverflow.com/questions/32190606/why-is-rxjs-not-canceling-my-promise)。我认为这两个问题都试图解决类似的问题。但在我的问题中,如果高速缓存已经有数据,我想取消或不发起promise/ajax调用。 –