在Mojolicious中,呈现Promise响应的正确方法是什么?在下面的代码中,我得到:
[2023-04-12] [trace] Template "example/search.html.ep" not found
[2023-04-12] [trace] Nothing has been rendered, expecting delayed response
1.它为什么要找example/search.html.ep
?我又没问。
1.我正在渲染内容... Mojo等不及了?
我的示例应用程序有3个文件:
1. script/my_app
#!/usr/bin/env perl
use strict;
use warnings;
use Mojo::File qw(curfile);
use lib curfile->dirname->sibling('lib')->to_string;
use Mojolicious::Commands;
Mojolicious::Commands->start_app('MyApp');
2. lib/MyApp.pm
package MyApp;
use Mojo::Base 'Mojolicious', -signatures;
sub startup ($self) {
$self->secrets('s3cret');
my $r = $self->routes;
$r->get('/')->to('Example#index');
$r->post('/')->to('Example#search');
}
1;
3. lib/MyApp/Controller/Example.pm
package MyApp::Controller::Example;
use Mojo::Base 'Mojolicious::Controller', -signatures;
sub index ($self)
{
return $self->render(inline => '<html><body><form method="post"><textarea name="numbers" maxlength="11">123</textarea><button type="submit">Go</button></form></body></html>');
}
sub search ($self)
{
my $v = $self->validation;
$v->required("numbers");
return $self->render(text=>"Validation Error") if $v->has_error;
my $numbers = $v->param("numbers");
my @numbers = split(/\r?\n/, $numbers);
Mojo::Promise
->map(
{concurrency => 2},
sub {
$self->ua->get_p("https://httpbin.org/delay/1?q=$_" => {'api-key'=>'shhh'});
}, @numbers)
->then(
sub{
my @results = @_;
my @json = map { $_->[0]->res->json } @results;
return $self->render(json => \@json);
})
->catch(
sub {
my $err = shift;
return $self->render(text => $err);
})
->wait;
#return $self->render(text => "This shall result is 'Unhandled rejected promise: A response has already been rendered'");
}
1;
要运行该应用程序,我需要:
morbo script/my_app
然后导航到http://localhost:3000
并发布表单。多行将导致并发调用。
1条答案
按热度按时间js81xvg61#
在调用Promise之前添加一个
render_later
:如果没有它,当函数
search
退出时,Mojolicious将默认渲染关联的模板(example/search.html.ep
),并失败,因为此模板不存在(请参阅Mojolicious::Guide::Rendering中的自动渲染)。render_later
禁用此自动渲染,基本上告诉Mojolicious“保持连接打开,我稍后会渲染”。你的困惑可能来自于
wait
的使用,它在这个上下文中并没有真正的“等待”。如果你在整个promise的前后添加一个print:然后日志将是:
这确实表明
wait
并没有真正等待(如果你不相信,你甚至可以在then
和catch
中添加打印:它们将在Before
之后打印)。看看
wait
的文档,它说:启动“ioloop”,并在promise被实现或拒绝后再次停止它,当“ioloop”已经在运行时不做任何事情。
在这里,由于您正在运行服务器,IOLoop始终运行,因此
wait
什么也不做。这实际上是可取的:如果wait
实际上要等待,那么使用Promise就没有意义了。另一方面,当您单独使用Mojo::Promise时(即不在Mojolicious服务器中),您可能需要手动使用
wait
运行IOLoop,以便在promise完成之前不退出脚本。