2010-12-08 50 views
1

我正在使用反應式擴展來調用異步方法,並且我想要緩存結果並將其返回給該方法的後續調用。創建IObservable並立即返回緩存的異步操作的結果

如何創建一個Observable實例,將其返回並提供訂閱需要的數據(cacheResult)?

public IObservable<Bar> GetBars(int pageIndex, int pageSize) 
{ 
    var @params = new object[] { pageIndex, pageSize }; 
    var cachedResult = _cache.Get(@params); 
    if (cachedResult != null) 
    { 
// How do I create a Observable instance and return the 'cacheResult'... 
return ... 
    } 

    var observable = new BaseObservable<Bar>(); 
    _components.WithSsoToken(_configuration.SsoToken) 
     .Get(@params) 
     .Select(Map) 
     .Subscribe(c => 
        { 
          _cache.Add(@params, c); 
          observable.Publish(c); 
          observable.Completed(); 
        }, exception => 
        { 
         observable.Failed(exception); 
         observable.Completed(); 
        }); 

     return observable; 
} 

回答

3

我相信你正在尋找Observable.Return

return Observable.Return((Bar)cachedResult); 

在一個不相關的注意事項:

  • 沒有必要返回一個BaseObservable<T>。您應該返回一個Subject<T>,因爲它可以執行您的實現,但是線程安全(您也應該在返回值上調用.AsObservable()以使其無法返回)。
  • 您使用Do的值添加到緩存:

var observable = new Subject<Bar>(); 
_components.WithSsoToken(_configuration.SsoToken) 
    .Get(@params) 
    .Select(Map) 
    .Subscribe(c => 
    { 
     _cache.Add(@params, c); 
     observable.OnNext(c); 
     observable.OnCompleted(); 
    }, exception => 
    { 
     observable.OnError(exception); 
    }); 

return observable.AsObservable(); 
+0

感謝您的回答和所有信息 – AwkwardCoder 2010-12-08 17:36:41

2

方便的是,我寫了一個類,做這種模式適合你,檢查出來:

https://github.com/xpaulbettsx/ReactiveXaml/blob/master/ReactiveXaml/ObservableAsyncMRUCache.cs

var cache = new ObservableAsyncMRUCache<int, int>(
    x => Observable.Return(x*10).Delay(1000) /* Return an IObservable here */, 
    100 /*items to cache*/, 
    5 /* max in-flight, important for web calls */ 
    ); 

IObservable<int> futureResult = cache.AsyncGet(10); 

futureResult.Subscribe(Console.WriteLine); 
>>> 100 

,它正確地處理一些棘手的事情:

  • 它緩存最近n項和扔掉未使用
  • 它確保不超過n項是在同一運行項目時間 - 如果您不這樣做,如果緩存爲空,您可以輕鬆產生數千個網絡電話
  • 如果您連續詢問同一項目兩次,第一個請求將啓動一個請求,第二個請求調用將等待第一個調用,而不是產生相同的請求,因此您不會最終重複查詢數據。