简短版本:如何在自己的代码(https://github.com/akavache/Akavache/blob/501b397d8c071366c3b6783aae3e98695b3d7442/src/Akavache/Portable/JsonSerializationMixin.cs#L202)中实现像Akavache一样的GetAndFetchLatest
方法-而不添加Akavache?
长版:
我有一个从磁盘返回T列表的方法,我有一个从HTTP服务返回相同类型List<T>
的方法。
两者都包装为Task<List<T>>
异步
在我的视图模型中,我只想调用1个返回Observable<List<T>>
的方法。
因此,在ViewModel中,我使用.Subscribe()
方法来更新UI。
本质上,需要两次通知我数据可用,并且订阅中的代码也将进行两次。
Akavache可以使用GetAndFetchLatest
方法的形式使用此功能...但是我对RX的理解还不够流利,无法理解如何使用2个数据方法调用自己实现此功能。
注意:所以我不想等待这两个任务!我想同时触发它们,并在它们返回数据时立即触发Observable
。
有小费吗?
最佳答案
给定Task<List<T>> GetFromWeb()
和Task<List<T>> GetFromDisk()
,简单的答案是这样的:
var merged = Observable.Merge(
GetFromWeb().ToObservable(),
GetFromDisk().ToObservable()
);
//Same thing using extension syntax
var simply = GetFromWeb().ToObservable()
.Merge(GetFromDisk().ToObservable());
但是,这不能解决
GetFromWeb
在GetFromDisk
之前完成的不太可能但可能的情况,在这种情况下,我假设您想忽略GetFromDisk
的结果。为了解决这个问题,您将需要一些体操:public IObservable<T> Prioritize<T>(params IObservable<T>[] orderedByDescendingPriority)
{
return orderedByDescendingPriority
.Select((o, i) => o.Select(item => Tuple.Create(orderedByDescendingPriority.Length - i, item)))
.Merge()
.Select(t => new Func<Tuple<int, T, bool>, Tuple<int, T, bool>>(t2 => Tuple.Create(Math.Max(t2.Item1, t.Item1), t.Item2, t.Item1 >= t2.Item1)))
.Scan(Tuple.Create(0, default(T), false), (t, f) => f(t))
.Where(t => t.Item3)
.Select(t => t.Item2);
}
var merged = Prioritize(
GetFromWeb().ToObservable(),
GetFromDisk().ToObservable()
);
编辑:
如果您总是希望
GetFromDisk
总是显示在GetFromWeb
之前,那么这是一个简单的Concat
操作。之所以可行,是因为.NET任务在您引用其功能后即自动启动: var t1 = GetFromDisk();
var t2 = GetFromWeb();
var merged = Observable.Concat(
t1.ToObservable(),
t2.ToObservable()
);
关于c# - 尽快合并请求并产生结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44133100/