$mech = new WWW::Mechanize(
onerror => sub {
say "Failed to get " . $mech->uri . ". Retrying.";
$mech->get($mech->uri);
}
);
如何让上述代码生效?我想引用Mechanize对象刚刚尝试获取的URI,然后重新尝试,但我无法解决如何在构造函数的调用中引用它。
答案 0 :(得分:1)
这是解决此问题的错误方法。 WWW::Mechanize
想在此处使用croak
兼容函数,以便能够在致命错误时退出。它将传递一个字符串列表,$mech
对象将不可见 - 也不一定有效。
如果要重试请求,请使用try
块将该逻辑放在请求周围。如果要将此概括为所有请求,请将WWWM
。
答案 1 :(得分:1)
除了失败的请求之外还有很多其他条件可以触发你的onerror
处理程序;在这些情况下,发送新请求没有意义。
您应该捕获$mech->get
抛出的异常并重新抛出任何非连接错误。您可以在子例程中执行此操作:
use strict;
use warnings 'all';
use 5.010;
use Try::Tiny;
use WWW::Mechanize;
sub retry {
my ($mech, $uri, $options) = @_;
$options //= {};
my $method = $options->{method} // 'get';
my $retries = $options->{retries} // 3;
my $interval = $options->{interval} // 3;
_try_request($mech, $uri, $method);
while (! $mech->success && $retries-- > 0) {
warn "Failed " . uc($method) . "ing $uri. Re-trying ...\n";
sleep $interval;
_try_request($mech, $uri, $method);
}
}
sub _try_request {
my ($mech, $uri, $method) = @_;
try {
$mech->$method($uri);
}
catch {
die $_ unless /Can't connect/; # re-throw other errors
};
}
my $mech = WWW::Mechanize->new;
retry($mech, 'http://www.stackoverflow.comx', { retries => 1 });
输出:
Failed GETing http://www.stackoverflow.comx. Re-trying ...
或者,您可以继承WWW :: Mechanize并覆盖请求方法。这样可以避免必须传递$mech
对象。