Nathan
Nathan

Reputation: 6216

How can I check for errors inside an RX Finally method?

The following code throws an error in the iterator (on purpose for testing). As you can see, the subscription easily gets hold of the exception using the onError parameter of the Subscribe method, but what I can't seem to work out is how the finally method could test/get hold of the exception (and therefore modify follow-up behaviour depending on the outcome)

static void Main(string[] args)
{
    // pseudo sequence
    var sequence = Observable.GenerateWithTime(
            (double)0, 
            i => i < 10, 
            i => i += 0.5, 
            i => {
                if(i < 6) return i;

                throw new InvalidOperationException();
            },
            i => TimeSpan.FromSeconds(1)
            ).Timestamp().Finally(() => Console.WriteLine("finally!"));


    using (
        sequence.Subscribe(x =>
            {
                Console.WriteLine(x);
            },
            err => Console.WriteLine(err.ToString())  // Write error to console
        )
    )
    {
            Console.ReadLine();
    }

    Console.ReadLine();
}

Note: this code is for demo purposes only, but it does work :)

Update

The following modifications to the demo above allowed the desired behaviour - thanks to James Hay.

    static void Main(string[] args)
    {
        bool errored = false;
        var sequence = Observable.GenerateWithTime(
                (double)0,
                i => i < 10,
                i => i += 0.5,
                i =>
                {
                    if (i < 6) return i;

                    throw new InvalidOperationException();
                },
                i => TimeSpan.FromSeconds(1)
                ).Catch(
                    new Func<Exception, IObservable<double>>(x => {
                        errored = true;
                        return Observable.Return((double)0);
                    })
                ).Timestamp().Finally(() => Console.WriteLine("finally!" + (errored?"(errored)":"")));

        using (
            sequence.Subscribe(objects =>
                {
                    Console.WriteLine(objects);
                },
                err => Console.WriteLine(err.ToString())
            )
        )
        {
                Console.ReadLine();
        }

        Console.ReadLine();
    }

Upvotes: 2

Views: 364

Answers (1)

James Hay
James Hay

Reputation: 12700

Finally will happen after an error occurs OR the sequence completes. So there may not be an error when execution hits the Finally operator.

If you want something to happen within the sequence when the error is thrown look into the Catch operator.

So you could add a side effect and re-throw the error:

.Catch(ex =>
{
   //Add a side effect here

   return Observable.Throw(ex); 
})

Or you could just handle the error and continue on through the sequence in some way:

.Catch(ex => Observable.Return("Some continue on error observable")));

Upvotes: 4

Related Questions