2016-09-26 8 views
0
$mech = new WWW::Mechanize(
    onerror => sub { 
     say "Failed to get " . $mech->uri . ". Retrying."; 
     $mech->get($mech->uri); 
    } 
); 

Как я могу заставить вышеуказанный код работать? Я хочу обратиться к URI, что объект Mechanize просто попытался получить, а затем повторить попытку, но я не могу понять, как ссылаться на это внутри вызова конструктора.Как ссылаться на объект в анонимной подсистеме при вызове конструктора?

ответ

1

Это неправильный способ решить эту проблему. WWW::Mechanize хочет здесь croak-совместимую функцию, чтобы иметь возможность выйти из фатальной ошибки. Он будет передавать список строк, а объект $mech не будет виден - и не обязательно будет действительным.

Если вы хотите повторить запросы, поместите эту логику вокруг запросов с помощью блока try. Если вы хотите обобщить это на все запросы, подкласс WWWM.

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.

+0

Существует также [WWW :: Mechanize :: Plugin :: Retry] (https://metacpan.org/pod/WWW::Mechanize::Plugin::Retry), но он, кажется, сломан. – ThisSuitIsBlackNot

+0

Это правильный способ повторить попытку, по-моему (это то, что я делаю, просто не пытаюсь). Обработка исключений - это больше, чтобы все это покрыть, не так ли? Он должен работать только с проверкой объекта с помощью собственных методов? – zdim

+0

@zdim По умолчанию WWW :: Mechanize умирает при ошибке, поэтому вам нужно либо отключить «autocheck», либо trap trap. Я бы предпочел оставить 'autocheck', так что мех все равно может умереть автоматически в другом месте кода. – ThisSuitIsBlackNot

 Смежные вопросы

  • Нет связанных вопросов^_^