简短版本:如何在我自己的代码(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>>
的方法。
因此,在我的视图模型中,我使用.Subscribe()
方法来更新 UI。 从本质上讲,我需要收到两次数据可用的通知,并且订阅中的代码也将完成两次。
此功能在阿卡瓦切以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()
);