Help us understand the problem. What is going on with this article?

例外が発生したら一定時間待機してからリトライする

JavaScriptではSleepに相当する処理が無いので気軽にリトライができない。async/awaitがあれば比較的簡単に解決できるが、IEにそのような機能は無い。

Promiseを使うことで解決できる。PromiseであればpolyfillがあるためIEでも利用できる。

ただ、いざ書いてみると大変面倒だったためメモしておく。

function retry(fn, opt){
    opt = opt || {};
    opt.times = opt.times || 3;
    opt.delay = opt.delay || function() { return 1000 }; // ExpornentialBackoff したいとき
    opt.abort = opt.abort || function() { return false }; // 中断したいときは true を返す
    opt.count = 0;
    opt.error = [];

    // 初回は即実行して欲しい
    var promise = new Promise(function(resolve,reject){
        var result;
        try{
            result = fn()
            resolve(result);
        }catch(e){
            opt.count++;
            opt.error.push(e);
            reject(opt);
        }
    });
    var i = 0;
    for(; i < opt.times; i++){
        promise = promise.catch(function(opt){
            // リトライは間隔を開けて欲しい
            return new Promise(function(resolve,reject){
                setTimeout(function(){
                    var result;
                    try {
                        if (opt.abort()) { return }
                        result = fn();
                        resolve(result);
                    }catch(e){
                        opt.count++;
                        opt.error.push(e);
                        reject(opt);
                    }
                }, opt.delay());
            });
        });
    }
    return promise;
}

以下の必ず例外を発生する関数を retry に投入すると、コンソールに1秒間隔で日付を6回(1+5回)表示し、最後に "fail" を表示する。

function fail() {
    console.log(new Date());
    throw 1;
}
retry(fail, { times: 5 }).catch(function(e){ console.log("fail") })

一方で、例外を発生しない場合は日付が1回表示されて終了する。

function pass() {
    console.log(new Date());
}
retry(pass, { times: 5 }).catch(function(e){ console.log("fail") })

更に、以下は途中で正常終了するため、コンソールには 1, 2, 3, pass が表示されて終了する。

var i = 0;
function safe() {
    i++;
    console.log(i);
    if (i < 3) { throw 1 }
}
retry(safe, { times: 5 }).then(function(){ console.log("pass") }).catch(function(e){ console.log("fail") })

以上

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした