glopes
glopes

Reputation: 4380

How to ignore all notifications from an observable sequence except errors?

I am looking to create an observable that subscribes to an input source but then only keeps the error message (i.e. ignores elements and completion messages until someone calls Dispose).

Basically I am looking for something like Observable.IgnoreElements but that would work more like Observable.Never.

The problem is that IgnoreElements leaves both termination messages (success and error). I only want to leave the error notification and ignore when a sequence successfully terminates. The Never method does this, but only generates an observable sequence, you cannot create it from another sequence.

Upvotes: 1

Views: 333

Answers (3)

Jason Boyd
Jason Boyd

Reputation: 7029

If I understand your question then I think this will work.

given an observable named source:

source.Materialize().Where(x => x.Kind == NotificationKind.OnError);

Upvotes: 1

Timothy Shields
Timothy Shields

Reputation: 79441

If what you want is to ignore all updates except for a single exception, if it occurs, then you can do this:

public static IObservable<T> OnlyError<T>(this IObservable<T> source)
{
    return Observable.Create<T>(
        observer => source.Subscribe(
            value => { },
            observer.OnError));
}

(The rest of the answer is no longer relevant because the question was changed.)

If you want to have multiple exceptions in a single sequence, the solution is a little more involved.

The implicit contract for IObserver<T> is that it will be called according to this pattern:

OnNext* [OnError|OnCompleted]

That is, OnError can be called at most once, and it ends the sequence. See the following excerpt from Observer Design Pattern Best Practices:

Once the provider calls the OnError or IObserver<T>.OnCompleted method, there should be no further notifications, . . .

If you want to have a sequence that can have multiple "errors," define something like this:

interface ITry<T>
{
    bool HasValue { get; }
    T Value { get; }
    Exception Error { get; }
}

And then use it like this:

IObservable<ITry<T>>

Keep IObserver<T>.OnError(Exception) meaning something went wrong with the sequence itself, not with the items in the sequence.

Upvotes: 3

glopes
glopes

Reputation: 4380

Turns out there is an obvious solution... simply concatenate to Never, like this:

IObservable<TSource> Never<TSource>(IObservable<TSource> source)
{
    return source.IgnoreElements().Concat(Observable.Never<TSource>());
}

Upvotes: 2

Related Questions