さんまがおいしい季節だねー(´・ω・`)

arguments.calleeとsetTimeoutを使ってJavaScriptのリトライ処理を簡単に書く方法

JavaScript — タグ: — さくら @ 2010/07/02 17:50

jQuery のソースから拾ってきたネタなんすが、arguments.callee と setTimeout を使ったリトライ処理が超便利なのでご紹介。

まず基本形はこんな感じす。

(function() {
    // なんか処理
    if (error) {
        setTimeout(arguments.callee, 20);
    }
})();

上のコードは error が真のとき20マイクロ秒後に無名関数の実行をリトライします。20マイクロ秒だとリトライ間隔が短いような気がするかもしれませんが、リトライ回数は1秒に50回ですので言うほどでもないです。

arguments.callee は関数内でのみ参照可能で、実行中の関数自身への参照を保持します。上の例では arguments.callee は無名関数への参照となります。setTimeout に arguments.callee を渡すその関数を再実行することになります。

実用的なケースで言うと ajax のエラー処理なんかどうでしょう。

ぶっちゃけ ajax のプログラム書いてると、403 とか 404 とかじゃないエラーは一定時間したらリトライさせたいとか多いんじゃないでしょうか。500 とかだいたいバグですし、ネットワークタイムアウトのときはマジでリトライしたい訳ですし。

そんな時こそ arguments.callee ですよ奥さん!!wコードが簡単になること請け合いです。

(function() {
    var callee = arguments.callee;
    $.ajax({
        url: 'http://...',
        error: function(xhr, status, e) {
            switch (xhr.status) {
            case 403: case 404:
                throw(xhr.status + ' ' + xhr.statusText);
                break;
            default:
                setTimeout(callee, 60000);    // 60000ms = 1分
                break;
            }
        }
    });
})();

error ハンドラの無名関数内で arguments.callee を参照すると error ハンドラそのもの(function(xhr, …) の方)になりますので、リトライしたい範囲を無名関数で括ってその arguments.callee を(一旦変数に入れてから)呼び出す必要があります。

この方法の便利なところは、エラーによるリトライが後から必要になった場合でも、リトライが必要な箇所を無名関数で括ってしまえば良いだけなので記述が簡単な点です。

似たような処理を setInterval を使って書くこともできますが、リトライを止める時に clearInterval を呼び出さないといけないが結構面倒だったりします。どの程度面倒かは自分で比べてかーさい。

ということで、ある処理が成功するまでリトライするコード(は JavaScript では割と出てくると思います)を書くなら、arguments.callee と setTimeout を組み合わせた方が便利だよっつーお話ですた。


てゆーか arguments.callee ちゃんマジ便利www

続く…

1件のコメント »

  1. [...] http://sakuratan.biz/archives/2131 [...]

この投稿へのコメントの RSS フィード。 TrackBack URI

コメントする

Copyright © 2017 さくらたんどっとびーず | powered by WordPress with Barecity