Skip to content

Instantly share code, notes, and snippets.

/promises.diff Secret

Created October 31, 2017 23:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/692695c43f328b7d7ee270601e4549fc to your computer and use it in GitHub Desktop.
Save anonymous/692695c43f328b7d7ee270601e4549fc to your computer and use it in GitHub Desktop.
diff --git a/lib/Mojo/UserAgent.pm b/lib/Mojo/UserAgent.pm
index 97d39b65d..e5622be58 100644
--- a/lib/Mojo/UserAgent.pm
+++ b/lib/Mojo/UserAgent.pm
@@ -34,6 +34,10 @@ for my $name (qw(DELETE GET HEAD OPTIONS PATCH POST PUT)) {
my ($self, $cb) = (shift, ref $_[-1] eq 'CODE' ? pop : undef);
return $self->start($self->build_tx($name, @_), $cb);
};
+ monkey_patch __PACKAGE__, lc($name) . '_p', sub {
+ my $self = shift;
+ return $self->start_p($self->build_tx($name, @_));
+ };
}
sub DESTROY { Mojo::Util::_global_destruction() or shift->_cleanup }
@@ -61,6 +65,22 @@ sub start {
return $tx;
}
+sub start_p {
+ my ($self, $tx) = @_;
+
+ my $promise = Mojo::IOLoop->delay;
+ $self->start(
+ $tx => sub {
+ my ($self, $tx) = @_;
+ my $err = $tx->error;
+ $promise->resolve($tx) unless $err && $err->{code};
+ $promise->reject($err->{message});
+ }
+ );
+
+ return $promise;
+}
+
sub websocket {
my ($self, $cb) = (shift, pop);
$self->start($self->build_websocket_tx(@_), $cb);
@@ -403,19 +423,14 @@ Mojo::UserAgent - Non-blocking I/O HTTP and WebSocket user agent
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
- # Concurrent non-blocking requests (synchronized with a delay)
- Mojo::IOLoop->delay(
- sub {
- my $delay = shift;
- $ua->get('mojolicious.org' => $delay->begin);
- $ua->get('cpan.org' => $delay->begin);
- },
- sub {
- my ($delay, $mojo, $cpan) = @_;
- say $mojo->result->dom->at('title')->text;
- say $cpan->result->dom->at('title')->text;
- }
- )->wait;
+ # Concurrent non-blocking requests (synchronized with promises)
+ my $mojo = $ua->get_p('mojolicious.org');
+ my $cpan = $ua->get_p('cpan.org');
+ $mojo->all($cpan)->then(sub {
+ my ($mojo, $cpan) = @_;
+ say $mojo->[0]->result->dom->at('title')->text;
+ say $cpan->[0]->result->dom->at('title')->text;
+ })->wait;
# WebSocket connection sending and receiving JSON via UNIX domain socket
$ua->websocket('ws+unix://%2Ftmp%2Fmyapp.sock/echo.json' => sub {
@@ -881,6 +896,22 @@ to perform requests non-blocking.
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
+=head2 start_p
+
+ my $promise = $ua->start_p(Mojo::Transaction::HTTP->new);
+
+Same as L</"start">, but performs all requests non-blocking and returns a
+L<Mojo::IOLoop::Delay> object instead of accepting a callback.
+
+ my $tx = $ua->build_tx(GET => 'http://example.com');
+ $ua->start_p($tx)->then(sub {
+ my $tx = shift;
+ say $tx->result->body;
+ })->catch(sub {
+ my $err = shift;
+ warn "Connection error: $err";
+ })->wait;
+
=head2 websocket
$ua->websocket('ws://example.com' => sub {...});
diff --git a/lib/Mojolicious/Guides/Tutorial.pod b/lib/Mojolicious/Guides/Tutorial.pod
index 360ce7d0d..296930ae1 100644
--- a/lib/Mojolicious/Guides/Tutorial.pod
+++ b/lib/Mojolicious/Guides/Tutorial.pod
@@ -868,20 +868,15 @@ L<Mojo::JSON> and L<Mojo::DOM> this can be a very powerful tool.
# Concurrent non-blocking
get '/titles' => sub {
my $c = shift;
- $c->delay(
- sub {
- my $delay = shift;
- $c->ua->get('http://mojolicious.org' => $delay->begin);
- $c->ua->get('https://metacpan.org' => $delay->begin);
- },
- sub {
- my ($delay, $mojo, $cpan) = @_;
- $c->render(json => {
- mojo => $mojo->result->dom->at('title')->text,
- cpan => $cpan->result->dom->at('title')->text
- });
- }
- );
+ my $mojo = $ua->get_p('http://mojolicious.org');
+ my $cpan = $ua->get_p('https://metacpan.org');
+ $mojo->all($cpan)->then(sub {
+ my ($mojo, $cpan) = @_;
+ $c->render(json => {
+ mojo => $mojo->[0]->result->dom->at('title')->text,
+ cpan => $cpan->[0]->result->dom->at('title')->text
+ });
+ })->wait;
};
app->start;
diff --git a/t/mojo/user_agent.t b/t/mojo/user_agent.t
index 3d49b3689..6e2c6782a 100644
--- a/t/mojo/user_agent.t
+++ b/t/mojo/user_agent.t
@@ -331,6 +331,23 @@ ok $success, 'successful';
is $code, 200, 'right status';
is $body, '{"hello":"world"}', 'right content';
+# Promises
+my @results;
+my $p1 = $ua->get_p('/');
+my $p2 = $ua->get_p('/');
+$p1->all($p2)->then(
+ sub {
+ my ($first, $second) = @_;
+ push @results, $first, $second;
+ }
+)->wait;
+ok $results[0][0]->success, 'successful';
+is $results[0][0]->res->code, 200, 'right status';
+is $results[0][0]->res->body, 'works!', 'right content';
+ok $results[1][0]->success, 'successful';
+is $results[1][0]->res->code, 200, 'right status';
+is $results[1][0]->res->body, 'works!', 'right content';
+
# Built-in web server times out
$ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton);
my $log = '';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment