繁体   English   中英

创建一个IObservable并立即返回缓存的异步操作的结果

[英]Create an IObservable and return the result of a cached async operation immediately

我正在使用反应式扩展来调用异步方法,并且我想缓存结果,并将其返回给以后对该方法的调用。

如何创建一个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;
}

我相信您正在寻找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();

方便地,我编写了一个为您执行此模式的类,请检查一下:

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个-如果您不这样做,则可以在缓存为空的情况下轻松产生数千个Web调用
  • 如果您连续两次要求相同的项目,则第一个请求将发起一个请求,而第二个调用将等待第一个请求,而不是生成相同的请求,因此您不会最终重复查询数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM