2013/12/08

Futures advent day 8

Day 8 - Handling Successes and Failures

We have seen how the then and else methods allow us to chain a sequence of code together, dependent on whether the previous succeeded or failed, in order to implement control flow that processes values and handles exceptions. Because each code block itself returns a future, we can "catch" exceptions and turn them into successful results, or we can throw "exceptions" if we don't like a successful result we received. However, sometimes it's convenient to split the control flow after a future, invoking a choice of two different code blocks depending on its success or failure. This way, the "then" handling code isn't going to be confused by a successful return from an exception handler, nor is the "else" code going to get confused if the "then" block dies. To do this, we can use the two-argument version of then.

my $f = GET("http://my-site-here.com/news")
  ->then(
    sub { # on success
      my ( $response ) = @_;
      my $title = get_page_title( $response->content );
      return Future->new->done( $title );
    },
    sub { # on failure
      my ( $failure, $response ) = @_;
      if( $response->code == 204 ) { # No Content
         return Future->new->done( "(no title)" );
      }
      return Future->new->fail( $failure, $response );
    },
  );

It would not have been possible to easily write this code by a sequence of single-argument then and else; because either the else block following the then would be confused by any exceptions thrown by the get_page_title() function, or the then block following the else would be confused by receiving a string rather than the HTTP response. While this could be detected by checking the types of the arguments, it turns out to be more useful and safer in practice to have a two-argument form of then which splits the control flow appropriately.

<< First | < Prev | Next >

No comments:

Post a Comment