-
-
Save anonymous/692695c43f328b7d7ee270601e4549fc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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