如何在调用构造函数时引用匿名子中的对象?

时间:2016-09-26 03:12:12

标签: perl scope anonymous-function www-mechanize

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

如何让上述代码生效?我想引用Mechanize对象刚刚尝试获取的URI,然后重新尝试,但我无法解决如何在构造函数的调用中引用它。

2 个答案:

答案 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对象。