如果我正确理解了您想要的内容,则可以以非常直接的方式完成此操作,并且如果您稍微重构代码,则可以进行清理。
首先,将名字和姓氏触发器变成可观察对象。在下面的代码中,我使用了主题,但如果您能够使用静态 Observable 方法将它们“转换”为可观察对象,那就更好了;例如Observable.FromEvent
。
然后将获取结果的代码转换为 observable。在下面的代码中,我曾经Observable.Create
返回一个IEnumerable<string>
.
最后,您可以使用 Switch 运算符订阅每个新的 GetResults 调用并取消之前对 GetResults 的调用。
听起来很复杂,但代码很简单:
private Subject<string> _firstName = new Subject<string>();
private Subject<string> _lastName = new Subject<string>();
private Task<IEnumerable<string>> FetchResults(string firstName, string lastName, CancellationToken cancellationToken)
{
// Fetch the results, respecting the cancellation token at the earliest opportunity
return Task.FromResult(Enumerable.Empty<string>());
}
private IObservable<IEnumerable<string>> GetResults(string firstName, string lastName)
{
return Observable.Create<IEnumerable<string>>(
async observer =>
{
// Use a cancellation disposable to provide a cancellation token the the asynchronous method
// When the subscription to this observable is disposed, the cancellation token will be cancelled.
CancellationDisposable disposable = new CancellationDisposable();
IEnumerable<string> results = await FetchResults(firstName, lastName, disposable.Token);
if (!disposable.IsDisposed)
{
observer.OnNext(results);
observer.OnCompleted();
}
return disposable;
}
);
}
private void UpdateGrid(IEnumerable<string> results)
{
// Do whatever
}
private IDisposable ShouldUpdateGridWhenFirstOrLastNameChanges()
{
return Observable
// Whenever the first or last name changes, create a tuple of the first and last name
.CombineLatest(_firstName, _lastName, (firstName, lastName) => new { FirstName = firstName, LastName = lastName })
// Throttle these tuples so we only get a value after it has settled for 100ms
.Throttle(TimeSpan.FromMilliseconds(100))
// Select the results as an observable
.Select(tuple => GetResults(tuple.FirstName, tuple.LastName))
// Subscribe to the new results and cancel any previous subscription
.Switch()
// Use the new results to update the grid
.Subscribe(UpdateGrid);
}
快速提示:您确实应该将显式调度程序传递给 Throttle,以便您可以使用 TestScheduler 有效地对该代码进行单元测试。
希望能帮助到你。