- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在包装一些 API 调用来假装套接字结果 - 以几秒的间隔循环调用并在更改时发出结果。
使用 DistinctUntilChanged()
运算符时效果很好。但是,当结果是列表时,运算符始终发出结果,因为它与默认比较器不同。
这是我自定义的可观察对象,用于重复任务,无论成功还是失败,都会有一定的延迟。
public class TaskRepeatObservable<T> : IObservable<T>
{
private readonly Func<Task<T>> _taskFactory;
private readonly TimeSpan _repeatDelayTimeSpan;
private readonly ILogger _logger;
private Func<Exception, bool> _onError;
public TaskRepeatObservable(Func<Task<T>> taskFactory, TimeSpan repeatDelayTimeSpan = default(TimeSpan), Func<Exception, bool> onError = null)
{
_logger = new Log4NetLogger(GetType());
_logger.IsEnabled = false;
_taskFactory = taskFactory;
_repeatDelayTimeSpan = repeatDelayTimeSpan;
_onError = onError;
}
public IDisposable Subscribe(IObserver<T> observer)
{
var tokenSource = new CancellationTokenSource();
var cancellationToken = tokenSource.Token;
Task.Factory.StartNew(async () =>
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
var result = await _taskFactory();
observer.OnNext(result);
}
catch (Exception e)
{
_logger.Error(e, "Observable Error: " + e.Message);
if (_onError != null && !_onError.Invoke(e))
throw;
}
finally
{
try
{
if (_repeatDelayTimeSpan > TimeSpan.Zero)
await Task.Delay(_repeatDelayTimeSpan, cancellationToken);
}
catch (TaskCanceledException)
{
// ignored
}
}
}
}
catch (Exception e)
{
observer.OnError(e);
}
_logger.Debug("Observable is cancelled.");
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
return Disposable.Create(() =>
{
tokenSource.Cancel();
});
}
}
这是包装 API 调用的扩展。
public static class ObservableBuilder
{
///<summary>
///<para>Convert Task to Observable and emit only changed result, it's useful to wrap the api as socket-like.</para>
///</summary>
public static IObservable<T> Repeat<T>(this Func<Task<T>> taskFactory, TimeSpan delay = default(TimeSpan),
Func<Exception, bool> onError = null)
{
return new TaskRepeatObservable<T>(taskFactory, delay, onError).DistinctUntilChanged();
}
我的问题是 - 如何使 DistinctUntilChanged()
适用于任何结果,包括 List
或 Enumerable
。
注意到我尝试实现我自己的比较器。但我仍然不知道如何检查 T
的类型来为 DistinctUntilChanged()
public class IEnumerableComparer<T> : IEqualityComparer<IEnumerable<T>>
{
public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
{
return ReferenceEquals(x, y) || x != null && y != null && x.SequenceEqual(y);
}
public int GetHashCode(IEnumerable<T> obj)
{
// Will not throw an OverflowException
unchecked
{
return obj.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
}
}
}
这是简单的测试代码:
ObservableBuilder.Repeat(async () =>
{
var i = new List<int>() { 1, 2, 3, 4 };
return i;
}, TimeSpan.FromSeconds(1)).ToHotObservable().Subscribe(x => Logger.Info($"Result = {x}"));
我希望列表只发出一次结果。
最佳答案
如果你只想拥有一个Repeat
函数可以转换所有情况,但对于 IEnumerable
的工作方式有所不同s - 你必须使用一些反射。您需要检查是否输入 T
实现IEnumerable<Something>
如果是这样 - 使用 DistinctUtilChanged
的特殊比较器- 否则使用默认比较器。
首先,修改你的EnumerableComparer
的签名不会有什么坏处。一点,因为您将特别需要 IEqualityComparer<T>
,不是IEqualityComparer<IEnumerable<T>>
:
private class EnumerableComparer<T, TItem> : IEqualityComparer<T> where T : IEnumerable<TItem> {
public bool Equals(T x, T y) {
return ReferenceEquals(x, y) || x != null && y != null && x.SequenceEqual(y);
}
public int GetHashCode(T obj) {
// Will not throw an OverflowException
unchecked {
return obj.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
}
}
}
现在我们需要检查是否 T
是 IEnumerable
并通过反射创建此比较器的实例:
public static class ObservableBuilder {
public static IObservable<T> Repeat<T>(this Func<Task<T>> taskFactory, TimeSpan delay = default(TimeSpan),
Func<Exception, bool> onError = null) {
var ienum = typeof(T).GetInterfaces().FirstOrDefault(c => c.IsGenericType && c.GetGenericTypeDefinition() == typeof(IEnumerable<>));
if (ienum != null) {
// implements IEnumerable - create instance of comparer and use
var comparer = (IEqualityComparer<T>) Activator.CreateInstance(typeof(EnumerableComparer<,>).MakeGenericType(typeof(T), ienum.GenericTypeArguments[0]));
return new TaskRepeatObservable<T>(taskFactory, delay, onError).DistinctUntilChanged(comparer);
}
// otherwise - don't use
return new TaskRepeatObservable<T>(taskFactory, delay, onError).DistinctUntilChanged();
}
private class EnumerableComparer<T, TItem> : IEqualityComparer<T> where T : IEnumerable<TItem> {
public bool Equals(T x, T y) {
return ReferenceEquals(x, y) || x != null && y != null && x.SequenceEqual(y);
}
public int GetHashCode(T obj) {
// Will not throw an OverflowException
unchecked {
return obj.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
}
}
}
}
或者,您可以创建 IEqualityComparer<T>
每次都会检查 x
和y
实现IEnumerable<Something>
并进行相应的比较,但我预计与构建序列时只进行一次比较相比,每次比较的效率都会较低。
关于C# Rx DistinctUntilChanged() 用于任何结果,包括列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50383674/
在rxjs流中,我将distinctUntilChanged与lodash的isEqual一起使用,以过滤出重复的值。但是,它似乎无法正常工作。采取以下代码片段 import { isEqual }
对于 rxjs,我可以在使用 distinctUntilChanged 时提供初始值吗?当没有收到以前的值时,似乎完全跳过了等于检查。当它收到的第一个值是初始值时,我不想发出任何内容。 用例 就我而言
如何让 distinctUntilChanged 处理这样的对象 myObs = Observable.from([{foo: 'bar'}, {foo: 'bar'}]); myObs.distin
我开始使用 RxJs(使用 v5 测试版),但不知何故我无法弄清楚如何使用 distinctUntilChanged .如果我在 babel-node 中运行它,下面代码的输出是 [ 'a', 1 ]
你们能告诉我这里出了什么问题吗? RxJS Jsfiddle Demo 我原以为该值只会打印一次,但它打印了多次 function Search(sel) { let observable =
我有一个值流,我使用下限和上限来限制,为了减少日志记录量,我只想在值发生变化时发出它们。问题是以下代码段中的第二个 distinctUntilChanged() 仍然会产生重复项: Observabl
情况 我想知道是否可以重置 distinctUntilChanged 部分以便它重新接受重复的值。 所以我的情况是,现在我正在使用这样的函数(作为示例大大缩短)。 Rx.Observable.
我正在尝试使用 .distinctUntilChanged() 并且它在第一次后没有将值传递给 switchmap()。 RxTextView.textChanges(etUserQuery).deb
设置:RxSwift 4.2 Swift 4.1 Xcode 9.4.1 我目前正在使用 distinctUntilChanged 来获取唯一值。但就我而言,它仅适用于“排序”值。 例如这里: fun
我有一个对象流,我需要比较当前对象是否与前一个对象不同,在这种情况下会发出一个新值。我发现 distinctUntilChanged 运算符应该完全按照我的意愿行事,但出于某种原因,除了第一个之外,它
让我们考虑一下下面的代码 Rx.Observable.merge( Rx.Observable.just(1), Rx.Observable.just(1).delay(1000) ).dis
我有一个可观察的流设置如下。我有一个间隔,每两秒轮询一次。然后我 switchMap 进行两个相关的 API 调用(这里用 'of's 模拟)。之后,我想使用 distinctUntilChanged
我想在我的异步验证器中添加 debounceTime 和 distinctUntilChanged。 mockAsyncValidator(): AsyncValidatorFn { retu
我正在包装一些 API 调用来假装套接字结果 - 以几秒的间隔循环调用并在更改时发出结果。 使用 DistinctUntilChanged() 运算符时效果很好。但是,当结果是列表时,运算符始终发出结
我有一个连续发出项目的可观察对象,我需要处理每个项目(处理函数需要一些时间)。因此,同时在处理一个项目时,如果另一个项目发出相同的值,我可以忽略它,因为同样的事情已经在进行中。但是一旦当前项目被处理(
阅读 How to use RxJs distinctUntilChanged?和 this ,似乎 distinctUntilChanged 将输出流更改为仅提供不同的连续值。 我的意思是,如果相同
我是 Rxjs 新手我正在尝试了解 BehaviourSubject下面是我的代码 export interface State { items: Items[] } const defaul
当我出于某种原因在表单输入上按下一个键时,异步验证器没有检测到 distinctUntilChanged,它仍然发送 API 请求。例如,如果我按 35,删除 5,然后再次添加 5,它仍然会发送请求。
我有一个返回可观察值的方法,如下所示 constructor(private _http: HttpClient) {} getUsers(location){ return this._htt
令 orders$ 是如下所示的 RxJs 对象序列。我们使用 distinctUntilChanged() 监听更改,并根据更改的键采取不同的操作。我们能否在 tap() 内部知道哪个对象键实际发生
我是一名优秀的程序员,十分优秀!