正确结束可观察流的正确方法

时间:2020-02-07 10:45:43

标签: c# system.reactive

我有几种返回IObservable的方法。在所有情况下,我都将建立一个查询,该查询将导致返回的可观察值完成。通常,我一直在使用TakeUntil扩展方法。我在TakeUntil中使用的可观察类型包含一个标志,该标志告诉我是否存在问题。如何使用此方法使返回的Observable错误结束?我很喜欢TakeUntil重载,它允许可观察的对象以错误结尾。

当前,我破解了一种方法,该方法返回一个主题,该主题已订阅可观察查询,并且还订阅了我在TakeUntil中使用的其他可观察对象,以调用OnCompleted或OnError。我意识到这是一个糟糕的计划,但是我应该怎么做?任何帮助,不胜感激。

2 个答案:

答案 0 :(得分:0)

TakeUntil不同,您必须从与OnNextOnErrorOnCompleteted对应的三种情况中选择一种。并且已经有一个内置类型可以在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")为例外的错误结束。

相关问题