Subroutine Signatures - 子例程参数署名

There's more than one way to do it!
https://metacpan.org http://perlmonks.org
头像
523066680
Administrator
Administrator
帖子: 494
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 59 times
Been thanked: 96 times
联系:

Subroutine Signatures - 子例程参数署名

帖子 #1 523066680 » 2021年04月20日 02:20

在 Mojo::UserAgent 官方示例中,有一段非阻塞请求的示例

# Non-blocking request
$ua->get('mojolicious.org' => sub ($ua, $tx) { say $tx->result->dom->at('title')->text });
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

其中,sub ($ua, $tx) {} 的形式之前还未在Perl中用过。运行出现错误提示
> Mojo::Reactor::Poll: I/O watcher failed: Can't call method "result" on an undefined value

后来写爬虫要用到非阻塞请求,又懒得探索,就自己改成传统方式,局部变量接收默认回调参数 $ua, $tx

$ua->get('mojolicious.org' => sub {my ($ua, $tx) = @_; say $tx->result->dom->at('title')->text });


不过很快遇到新的需求,抓取的大量数据要分门别类地存储到指定的目录指定的文件,如何告诉这个回调函数指定的文件路径和文件名?想到了闭包,这样便可以传递更多参数。

以下代码根据 %list 中的城市名单,获取不同城市的物流数据并保存到相应JSON文件。

my $wdir = "D:/blah";
for my $city ( keys %list )
{
my $name = sprintf "%s/%s.json", $wdir, gbk($city);
$query->{"toCountryId"} = $ct_code->{$city}; # 城市ID 更新到请求数据中
$res = $ua->post( $url, to_json( $query ), closure->( $name ) );
}

$loop->start unless $loop->is_running;

sub closure
{
my ( $file ) = @_;
return sub {
my ($ua, $tx) = @_;
printf "%s\n", $file;
write_file( $file, $tx->result->body );
}
}


其实在 Mojolicious::Guides 中有相关介绍,只是之前忽视了,
https://docs.mojolicious.org/Mojolicious/Guides

>Signatures
On Perl 5.20+ you can also use the `-signatures` flag with Mojo::Base to enable support for subroutine signatures. Signatures are used in all examples for clarity, even when `-signatures` is omitted for brevity.

通过该特性以达到简洁代码的目的,(闭包似乎还是省不了)

my $wdir = "D:/blah";
for my $city ( keys %list )
{
my $name = sprintf "%s/%s.json", $wdir, gbk($city);
$query->{"toCountryId"} = $ct_code->{$city}; # 城市ID 更新到请求数据中
$res = $ua->post( $url, to_json( $query ), closure->( $name ) );
}

$loop->start unless $loop->is_running;

sub closure ($file) {
return sub ($ua, $tx) {
printf "%s\n", $file;
write_file( $file, $tx->result->body );
}
}


其他参考 Announcing Perl 7

回到 “Perl”

在线用户

用户浏览此论坛: 没有注册用户 和 2 访客