The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Promises - An implementation of Promises in Perl

VERSION

version 0.05

SYNOPSIS

  use AnyEvent::HTTP;
  use JSON::XS qw[ decode_json ];
  use Promises qw[ collect deferred ];

  sub fetch_it {
      my ($uri) = @_;
      my $d = deferred;
      http_get $uri => sub {
          my ($body, $headers) = @_;
          $headers->{Status} == 200
              ? $d->resolve( decode_json( $body ) )
              : $d->reject( $body )
      };
      $d->promise;
  }

  my $cv = AnyEvent->condvar;

  collect(
      fetch_it('http://rest.api.example.com/-/product/12345'),
      fetch_it('http://rest.api.example.com/-/product/suggestions?for_sku=12345'),
      fetch_it('http://rest.api.example.com/-/product/reviews?for_sku=12345'),
  )->then(
      sub {
          my ($product, $suggestions, $reviews) = @_;
          $cv->send({
              product     => $product,
              suggestions => $suggestions,
              reviews     => $reviews,
          })
      },
      sub { $cv->croak( 'ERROR' ) }
  );

  my $all_product_info = $cv->recv;

DESCRIPTION

This module is an implementation of the "Promise" pattern for asynchronous programming. Promises are meant to be a way to better deal with the resulting callback spaghetti that can often result in asynchronous programs.

Relation to the various Perl event loops

This module is actually Event Loop agnostic, the SYNOPSIS above uses AnyEvent::HTTP, but that is just an example, it can work with any of the existing event loops out on CPAN. Over the next few releases I will try to add in documentation illustrating each of the different event loops and how best to use Promises with them.

Relation to the Promise/A spec

We are, with some differences, following the API spec called "Promise/A" (and the clarification that is called "Promise/A+") which was created by the Node.JS community. This is, for the most part, the same API that is implemented in the latest jQuery and in the YUI Deferred plug-in (though some purists argue that they both go it wrong, google it if you care). We differ in some respects to this spec, mostly because Perl idioms and best practices are not the same as Javascript idioms and best practices. However, the one important difference that should be noted is that "Promise/A+" strongly suggests that the callbacks given to then should be run asynchronously (meaning in the next turn of the event loop). We do not do this because doing so would bind us to a given event loop implementation, which we very much want to avoid.

Relation to Promises/Futures in Scala

Scala has a notion of Promises and an associated idea of Futures as well. The differences and similarities between this module and the Promises found in Scalar are highlighted in depth in a cookbook entry below.

Cookbook

I have begun moving the docs over into a Cookbook. While this module is incredibly simple, the usage of it is quite complex and deserves to be explained in detail. It is my plan to grow this section to provide examples of the use of Promises in a number of situations and with a number of different event loops.

Promises::Cookbook::SynopsisBreakdown

This breaks down the example in the SYNOPSIS and walks through much of the details of Promises and how they work.

Promises::Cookbook::TIMTOWTDI

Promise are just one of many ways to do async programming, this entry takes the Promises SYNOPSIS again and illustrates some counter examples with various modules.

Promises::Cookbook::ChainingAndPipelining

One of the key benefits of Promises is that it retains much of the flow of a syncronous program, this entry illustrates that and compares it with a syncronous (or blocking) version.

Promises::Cookbook::ScalaFuturesComparison

This entry takes some examples of Futures in the Scala language and translates them into Promises. This entry also showcases using Promises with Mojo::UserAgent.

EXPORTS

deferred

This just creates an instance of the Promises::Deferred class it is purely for convenience.

collect( @promises )

The only export for this module is the collect function, which accepts an array of Promises::Promise objects and then returns a Promises::Promise object which will be called once all the @promises have completed (either as an error or as a success). The eventual result of the returned promise object will be an array of all the results (or errors) of each of the @promises in the order in which they where passed to collect originally.

when( @promises )

This is now deprecated, if you import this it will warn you accordingly. Please switch all usage of when to use collect instead.

SEE ALSO

"You're Missing the Point of Promises" http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/
http://wiki.commonjs.org/wiki/Promises/A
https://github.com/promises-aplus/promises-spec
http://docs.scala-lang.org/sips/pending/futures-promises.html
http://monkey.org/~marius/talks/twittersystems/

AUTHOR

Stevan Little <stevan.little@iinteractive.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Infinity Interactive, Inc..

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.