Существует много других условий помимо отказавшего запроса, который может вызвать ваш обработчик 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
.
Существует также [WWW :: Mechanize :: Plugin :: Retry] (https://metacpan.org/pod/WWW::Mechanize::Plugin::Retry), но он, кажется, сломан. – ThisSuitIsBlackNot
Это правильный способ повторить попытку, по-моему (это то, что я делаю, просто не пытаюсь). Обработка исключений - это больше, чтобы все это покрыть, не так ли? Он должен работать только с проверкой объекта с помощью собственных методов? – zdim
@zdim По умолчанию WWW :: Mechanize умирает при ошибке, поэтому вам нужно либо отключить «autocheck», либо trap trap. Я бы предпочел оставить 'autocheck', так что мех все равно может умереть автоматически в другом месте кода. – ThisSuitIsBlackNot