2017-04-01 95 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調用。 –