重定向之前Mojo :: IOLoop计时器出现问题

时间:2019-03-08 08:10:59

标签: perl mojolicious morbo

我的Mojolicious Controller中有一个子程序,当通过http帖子上传csv文件时会调用该子程序。 上传文件后,将显示一条消息,提示您“您将在x秒内被重定向”。 所以我想实现Mojo :: IOLoop :: Delay,作为回调我使用重定向语句。但是我得到了Morbo的以下错误:

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 个答案:

答案 0 :(得分:2)

redirect_to实际上是一个render,它呈现HTTP 302响应以进行重定向。您不能渲染两次,因此即使您在redirect_to调用之前一直保持事务处理,它也已经渲染了页面。因此,您要尝试执行的操作有两个实际选择:使用超时时间将执行重定向的javascript呈现页面,或使用元刷新标记呈现HTML页面,该HTML页面将在延迟后导致重定向。 MDN page讨论了这两种方法。

答案 1 :(得分:1)

uploadMojo::IOLoop->timer之后返回,没有任何等待计时器。您可以尝试改用Mojo::IOLoop->delay$delay->wait。但是我不确定它是如何工作的。因此,它可能只相当于sleep

您真的需要从Perl代码重定向吗?您可以使用setTimeout渲染一些js以达到相同的效果。

实际上,我建议将所有文本移动并重定向到js,并仅在upload中呈现带有某些状态信息的json。因此,您可以通过错误处理实现更好的UI。