Проблема с таймером Mojo::IOLoop перед перенаправлением
У меня есть подпрограмма в моем контроллере Mojolicious, которая вызывается, когда файл CSV загружается через сообщение HTTP. После загрузки файла выдается сообщение, в котором говорится, что "вы будете перенаправлены через x секунд". поэтому я хочу реализовать Mojo::IOLoop::Delay и в качестве обратного вызова я использую оператор перенаправления. Но я получаю следующую ошибку от Морбо:
Mojo::Reactor::EV: Timer failed: Transaction already destroyed at /usr/local/share/perl/5.22.1/Mojolicious/Plugin/DefaultHelpers.pm line 168.
код контроллера:
sub upload {
my $self = shift;
# Check file size
return $self->render(text => 'File is too big.', status => 200)
if $self->req->is_limit_exceeded;
# Process uploaded file
return $self->redirect_to('/') unless my $newCsv = $self->param('fileToUpload');
my $size = $newCsv->size;
my $name = $newCsv->filename;
my $delay = 2;
$self->render(text => "Thanks for uploading $size byte file $name.<br>
You will be redirected in $delay seconds");
Mojo::IOLoop->timer($delay => sub {
$self->redirect_to('/');
});
}
соответствующие маршруты:
$r->get('/')->to(controller => 'main', action => 'index');
$r->post('/uploadCsv')->to(controller => 'main', action => 'upload')->name('uploadCsv');
заранее спасибо
2 ответа
upload
возвращается после Mojo::IOLoop->timer
и ничто не ждет таймера. Вы можете попробовать использовать Mojo::IOLoop->delay и $delay->wait
вместо. Но я не уверен, как это работает. Так что это может быть эквивалентно просто sleep
,
Вам действительно нужно перенаправить из Perl-кода? Вы можете сделать некоторые JS с setTimeout
для того же эффекта.
На самом деле, я бы порекомендовал переместить весь текст и перенаправить на js и рендерить только json с некоторой информацией о состоянии внутри upload
, Таким образом, вы можете реализовать лучший интерфейс с обработкой ошибок.
redirect_to
эффективно render
который передает HTTP 302 ответ для перенаправления. Вы не можете выполнить рендеринг дважды, поэтому даже если вы продолжите транзакцию до redirect_to
позвоните, он бы уже сделал страницу. Таким образом, есть два фактических варианта того, что вы пытаетесь сделать; визуализировать страницу с использованием JavaScript, который будет выполнять перенаправление после истечения времени ожидания, или визуализировать HTML-страницу с мета-тегом обновления, который приведет к перенаправлению страницы после задержки. На этой странице MDN обсуждаются оба подхода.