【问题标题】:Problem with Mojo::IOLoop timer before redirect重定向前 Mojo::IOLoop 计时器的问题
【发布时间】:2019-03-08 08:10:58
【问题描述】:

我的 Mojolicious 控制器中有一个子程序,当通过 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');

提前谢谢你

【问题讨论】:

    标签: perl mojolicious morbo


    【解决方案1】:

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

    【讨论】:

    • 感谢您的回答。我选择了第三种解决方案:):我在我的 .html 中实现了一个带有超时的 JS 脚本。您认为这个解决方案是否也可行,或者它不是“最好的”解决方案?
    • @Chris 我认为这很适合您想要完成的任务,元刷新方法的唯一好处是它不需要用户启用 javascript。
    【解决方案2】:

    uploadMojo::IOLoop-&gt;timer 之后返回,并且没有任何东西等待计时器。您可以尝试改用Mojo::IOLoop->delay$delay-&gt;wait。但我不确定它是如何工作的。所以它可能等同于sleep

    你真的需要从 perl 代码重定向吗?你可以用setTimeout渲染一些js来达到同样的效果。

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

    【讨论】:

      猜你喜欢
      • 2016-08-08
      • 2017-10-07
      • 2016-03-22
      • 2018-06-21
      • 2011-02-07
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 2014-10-11
      相关资源
      最近更新 更多