2013-05-15 5 views
3

У меня есть PERL приложение, которое, например, параллельный поиск в гугле:Параллельные запросы в приложении Mojolicious

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

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

my $delay = Mojo::IOLoop->delay(sub { say 'DONE1 (should be before render)'; }); 

foreach my $i (1 .. 10) { 
    $delay->begin(); 

    $ua->get("http://www.google.ru/search?q=$i" => sub { 
     say $i; 
     $delay->end(); 
    }); 
} 

$delay->wait() unless $delay->ioloop->is_running(); 

say 'DONE2 (should be before render)'; 
say 'Found! (render)'; 

И это прекрасно работает:

6 
1 
7 
10 
3 
9 
2 
5 
8 
4 
DONE1 (should be before render) 
DONE2 (should be before render) 
Found! (render) 

Когда я использую этот код в приложении Mojolicious в контроллер:

package MyApp::Google; 

use Mojo::Base 'Mojolicious::Controller'; 

sub search { 

    my $self = shift; 

    my $delay = Mojo::IOLoop->delay(sub { $self->app->log->debug('DONE1 (should be before render)') }); 

    foreach my $i (1 .. 10) { 
     $delay->begin(); 

     $self->ua->get("http://www.google.ru/search?q=$i" => sub { 
      $self->app->log->debug($i); 
      $delay->end(); 
     }); 
    } 

    $delay->wait() unless $delay->ioloop->is_running(); 

    $self->app->log->debug('DONE2 (should be before render)'); 

    return $self->render_text('Found!'); 

} 

Это происходит в неправильном направлении:

[Wed May 15 11:07:32 2013] [debug] Routing to controller "MyApp::Google" and action "search". 
[Wed May 15 11:07:32 2013] [debug] DONE2 (should be before render) 
[Wed May 15 11:07:32 2013] [debug] 200 OK (0.005689s, 175.778/s). 
[Wed May 15 11:07:32 2013] [debug] 1 
[Wed May 15 11:07:32 2013] [debug] 8 
[Wed May 15 11:07:32 2013] [debug] 10 
[Wed May 15 11:07:32 2013] [debug] 5 
[Wed May 15 11:07:32 2013] [debug] 3 
[Wed May 15 11:07:32 2013] [debug] 9 
[Wed May 15 11:07:32 2013] [debug] 6 
[Wed May 15 11:07:32 2013] [debug] 2 
[Wed May 15 11:07:32 2013] [debug] 4 
[Wed May 15 11:07:32 2013] [debug] 7 
[Wed May 15 11:07:32 2013] [debug] DONE1 (should be before render) 

Я так думаю $delay->wait()не ждет. Почему это происходит?

ответ

5

В этом случае вам необходимо отключить автоматический рендеринг, вызвав метод render_later с контроллера. (http://mojolicio.us/perldoc/Mojolicious/Controller#render_later)

Просто добавьте следующую строку в поиска контроллера:

$self->render_later; 

Полный пример:

#!/usr/bin/perl -wl 
use Mojolicious::Lite; 

get '/' => sub { 
    my $self = shift; 
    $self->render_later; 
    my $delay = Mojo::IOLoop->delay(sub { 
     $self->app->log->debug('Delay finished!'); 
     $self->render(text => 'test!'); 
    }); 
    for my $i (0 .. 5) { 
     my $end = $delay->begin; 
     Mojo::IOLoop->timer($i => sub { 
      $self->app->log->debug($i); 
      $end->(); 
     }); 
    } 
}; 

app->start; 
+0

Дайте мне, пожалуйста, какой-то рабочий пример. Я не могу. Решение не решает проблему root: оно не ждет выполнения всех задач. – Tema

+0

О, извините. Вы также должны сделать фактическую визуализацию на ** закончить ** событие в задержке (первый аргумент функции ** Mojo :: IOLoop-> delay **). Полный пример я добавил в главный ответ. –

+3

Обратите внимание, что 'render_text' (и многие другие такие ярлыки) были удалены из Mojolicious 4.0 (который был выпущен сегодня). Вы должны использовать стандартную форму '$ self-> render (text => 'test!'); Вместо этого. –

Смежные вопросы