我有几种返回IObservable的方法。在所有情况下,我都将建立一个查询,该查询将导致返回的可观察值完成。通常,我一直在使用TakeUntil扩展方法。我在TakeUntil中使用的可观察类型包含一个标志,该标志告诉我是否存在问题。如何使用此方法使返回的Observable错误结束?我很喜欢TakeUntil重载,它允许可观察的对象以错误结尾。
当前,我破解了一种方法,该方法返回一个主题,该主题已订阅可观察查询,并且还订阅了我在TakeUntil中使用的其他可观察对象,以调用OnCompleted或OnError。我意识到这是一个糟糕的计划,但是我应该怎么做?任何帮助,不胜感激。
答案 0 :(得分:0)
与TakeUntil
不同,您必须从与OnNext
,OnError
和OnCompleteted
对应的三种情况中选择一种。并且已经有一个内置类型可以在Notification<T>
中捕获它。
我们需要做的就是使用Dematerialize
运算符将具体的通知转换为隐式通知。
这是一个示例流,如果流中出现值10,则会引发该流,但是如果任何值> = 9,则会完成该流。
var errorAt10 =
values.Select(value =>
{
if (value == 10)
return Notification.CreateOnError<long>(new Exception());
if (value >= 9)
return Notification.CreateOnCompleted<long>();
return Notification.CreateOnNext(value);
})
.Dematerialize();
如果需要,我们可以简化此操作
public static IObservable<T> NotifyAs<T>(this IObservable<T> source, Func<T, NotificationKind> choice, Exception exception = default)
{
return source.Select(value =>
{
switch (choice(value))
{
case NotificationKind.OnError:
return Notification.CreateOnError<T>(exception ?? new Exception());
case NotificationKind.OnCompleted:
return Notification.CreateOnCompleted<T>();
default:
return Notification.CreateOnNext(value);
}
})
.Dematerialize();
}
现在您可以将前面的示例重写为:
var errorAt10 =
values.NotifyAs(value =>
value == 10 ? NotificationKind.OnError :
value >= 9 ? NotificationKind.OnCompleted :
NotificationKind.OnNext
);
答案 1 :(得分:0)
您实际上不需要执行任何操作。您要的内容已经内置。
如果您以以下代码开头:
var source = Observable.Interval(TimeSpan.FromSeconds(1.0));
var ender = new Subject<Unit>();
var query = source.TakeUntil(ender);
query.Subscribe(x => Console.WriteLine(x));
然后,您只需为ender.OnError(new Exception("My exception"));
调用source
即可观察到以new Exception("My exception")
为例外的错误结束。