Question regarding Mojo::UserAgent non-blocking example

37 views
Skip to first unread message

Ronald Wong

unread,
Nov 2, 2017, 5:14:04 AM11/2/17
to Mojolicious

Hi All,


I have recently started learning how to write non-blocking http request and Mojo::UserAgent is the best one which can help me to overcome the proxy issue within the company environment.
While learning by following the example, there is something I do not understand from the code and raised a question in perlmonks:
http://www.perlmonks.org/?node_id=1202496;showspoiler=1202547-1


However, I am still clueless regarding the behaviour, could I ask your help in explaining it further?

http://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Non-blocking


The following is the code example:

use Mojo::UserAgent; use Mojo::IOLoop; my @urls = ( 'mojolicious.org/perldoc/Mojo/DOM', 'mojolicious.org/perldoc/Mojo', 'mojolicious.org/perldoc/Mojo/File', 'mojolicious.org/perldoc/Mojo/U +RL' ); my $ua = Mojo::UserAgent->new(max_redirects => 5); $ua->transactor->name('MyParallelCrawler 1.0'); my $delay = Mojo::IOLoop->delay; my $fetch; $fetch = sub { return unless my $url = shift @urls; my $end = $delay->begin; $ua->get($url => sub { my ($ua, $tx) = @_; say "$url: ", $tx->result->dom->at('title')->text; $end->(); $fetch->(); }); }; #Process two requests at a time $fetch->() for 1 .. 2; $delay->wait;


From the above example, at the last 2nd line, "$fetch->() for 1 .. 2;",
if I remove the for loop, the code will process the first URL only.

I suppose the $fetch is a recursion and the function calling itself within the function.
Shouldn't the code process 1 request each time if I remove the for loop?

I am wondering inside the $fetch function that $fetch->() should go before $end->()?

As following:
$fetch = sub {
...
$fetch->();

$end->();
});
};

instead of
$fetch = sub {
...
$end->();

$fetch->();
});
};


After the above change, the code will now process all the URLs one by one when it is only $fetch->().

And if I run it with for-loop like $fetch->() for 1 .. 2, it looks like processing 2 URLs in 1 go.
The code behaving much more like the original intended.

The problem with the original code is that if you are calling it 1 time only, at the time reaching the end of the event loop the condition may have satisfied and exit the program before it can call another function itself.(my guess) 
Am I correct with the above theory?


Thanks,
Ronald

Sebastian Riedel

unread,
Nov 2, 2017, 5:22:22 AM11/2/17
to mojol...@googlegroups.com
> $fetch = sub {
> ...
> $fetch->();
>
> $end->();
> });
> };

I think you are correct, this code is better.

--
Sebastian Riedel
http://mojolicio.us
http://github.com/kraih
http://twitter.com/kraih

Ronald Wong

unread,
Nov 2, 2017, 9:00:53 AM11/2/17
to Mojolicious
Many thanks for your reply and especially thanks for creating such great module!
Reply all
Reply to author
Forward
0 new messages