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

上記のコードを動作させるにはどうすればよいですか?私はMechanizeオブジェクトが取得しようとしたURIを参照して再試行したいが、コンストラクタへの呼び出しの中でこれを参照する方法を考えることはできない。コンストラクタの呼び出し時に匿名のサブオブジェクトを参照する方法は?

答えて

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'をオフにするか例外をトラップする必要があります。 mechがコード内のどこかで自動的に死ぬことができるように、私はむしろ 'autocheck'を残しておきます。 – ThisSuitIsBlackNot

関連する問題