使用Mojo :: IOLoop :: Delay的顺序请求

时间:2017-05-09 08:30:46

标签: perl asynchronous mojolicious

我需要以非阻塞模式获取URL列表,但不能并行获取。它应该是逐个顺序请求。我怎么能意识到这一点?

我找不到例子。文档和文章仅强调并行执行。

现在我的代码如下所示(简化):

my $delay = Mojo::IOLoop::Delay->new;

$delay->steps(
    sub {
        build_report();
        say "done";
    }
);

sub parse_data {
    ...;
    my $url = shift @urls;
    my $end = $delay->begin;
    $ua->get( $url => \&parse_data );
    $end->();
}

my $end = $delay->begin;
$ua->get( $url => \&parse_data );
$end->();
$delay->wait;

我希望使用Mojo::IOLoop::Delay来避免多次关闭。

2 个答案:

答案 0 :(得分:0)

我刚刚开始关注Mojo::IOLoop一个项目,但我还没有考虑过它。但我认为最简单的方法是构建一个闭包数组并将其传递给$delay->steps

use strict;
use warnings 'all';
use feature 'say';

use Mojo;

use constant URL => 'http://stackoverflow.com/questions/tagged/perl';

STDOUT->autoflush;

my $ua = Mojo::UserAgent->new;
my $delay = Mojo::IOLoop::Delay->new;

my @urls = ( URL ) x 10;

my @steps =  map {

    my $url = $_;

    sub {

        my $end = $delay->begin;

        $ua->get( $url => sub {
            my ( $ua, $txn ) = @_;

            $end->();

            if ( my $err = $txn->error ) {
                say $err->message;
            }
            else {
                my $res = $txn->success;
                say "@{$res}{qw/ code message /}";
            }
        });
    }

} @urls;


$delay->steps( @steps, sub { say 'Done' } );

Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

输出

200 OK
200 OK
200 OK
200 OK
200 OK
200 OK
200 OK
200 OK
200 OK
Done
200 OK

请注意,Done会在最终get的状态行之前打印,因为我已立即调用$end->()来回复,假设对响应的任何处理都没有。需要同步

如果您不想要,那么只需将$end->()移至回调的末尾即可。然后延迟将等到产生输出之后再发送另一个请求

答案 1 :(得分:0)

顺序请求非常容易实现。

网络服务器

#!/usr/bin/perl
use Mojo::Base -strict;

use Mojolicious::Lite;

get '/' => sub {
  my $c = shift->render_later;

  $c->delay(sub {
    my $delay = shift;
    $c->ua->get('https://google.ru' => $delay->begin);
  }, sub {
    my ($delay, $tx) = @_;
    $tx->res->body; # body of the google.ru
    $c->ua->get('https://twitter.com' => $delay->begin);
  }, sub {
    my ($delay, $tx) = @_;
    $tx->res->body; # body of the twitter.com
    $c->render(text => 'Done');
  });
};

app->start;

<强>脚本

#!/usr/bin/perl
use Mojo::Base -strict;

use Mojo::IOLoop;
use Mojo::UserAgent;

my $ua = Mojo::UserAgent->new;

Mojo::IOLoop->delay(sub {
  my $delay = shift;
  $ua->get('https://www.google.ru' => $delay->begin);
}, sub {
  my ($delay, $tx) = @_;
  $tx->res->body; # body of the google.ru
  $ua->get('https://twitter.com' => $delay->begin);
}, sub {
  my ($delay, $tx) = @_;
  $tx->res->body; # body of the twitter.com
  warn 'DONE';
})->wait;

脚本(动态请求)

Example here