diff --git a/lib/Mojo/Promise.pm b/lib/Mojo/Promise.pm index c6b6b097d7..33d71ab514 100644 --- a/lib/Mojo/Promise.pm +++ b/lib/Mojo/Promise.pm @@ -182,7 +182,63 @@ Mojo::Promise - Promises/A+ =head1 DESCRIPTION L is a Perl-ish implementation of -L. +L. Promises allow asynchronous +operations to be handled in a controlled and composable way. + +A promise wraps a single asynchronous operation that will either be +fulfilled or rejected with an error in the future. A fulfilled promise +will have a stable value that is guaranteed to not change anymore. +Also in case the promise fails, the resuting error will not change. + +Promises have three states, they start out as C and you call +L to transition them to C, or +L to transition them to C. + +The example below runs an asynchronous HTTP GET request wrapped in a promise. +Upon receiving a successful response the promise will be resolved with the +transaction as resulting value. In case of errors the promise is rejected +with the error message taken from the received response. + + sub get { + my $promise = Mojo::Promise->new; + $ua->get(@_ => sub { + my ($ua, $tx) = @_; + my $err = $tx->error; + $promise->resolve($tx) if !$err || $err->{code}; + $promise->reject($err->{message}); + }); + return $promise; + } + +The C function will return a promise object immediatly and perform +no further operations until a response is received. + +The most common way of dealing with promises is using the method +L. The will allow to call the provided callback +upon fulfillment of the promise. + + my $promise = get("http://mojolicious.org"); # returns a promise + $promise->then(sub { + my ($self, $tx) = @_; + say "Mojolicous website returns " . $tx->res->code; + }); + +Through the composable nature of promises you are now allowed to chain +operation by using the various mechanisms the promise object provides. + +For example a new promise can be created to resolve only after both +GET operations have completed using the method L. + + my $promise1 = get("http://mojolicious.org"); + my $promise2 = get("https://perlbrew.pl/"); + my $both = Mojo::Promise->all($promise1, $promise2)->then(sub { + my ($tx1, $tx2) = @_; + say "Mojolicous website returns " . $tx1->res->code; + say "Perlbrew website returns " . $tx2->res->code; + }); + +To handle errors the catch method can be used. The provided callback +will be passed the error resulting from the failed/rejected operation. =head1 ATTRIBUTES diff --git a/lib/Mojolicious/Guides/Cookbook.pod b/lib/Mojolicious/Guides/Cookbook.pod index d0609c7c03..e288218dc1 100644 --- a/lib/Mojolicious/Guides/Cookbook.pod +++ b/lib/Mojolicious/Guides/Cookbook.pod @@ -619,7 +619,7 @@ that create them for you. app->start; -To create promises maually you just wrap your continuation-passing style APIs in +To create promises manually you just wrap your continuation-passing style APIs in functions that return promises. Here's an example for how L works internally. @@ -645,9 +645,7 @@ L works internally. say $tx->result->dom->at('title')->text; })->wait; -Promises have three states, they start out as C and you call -L to transition them to C, or -L to transition them to C. +See L for more examples on working with promises. =head2 Timers