关于javascript:配置jQuery以在失败时重试ajax调用

Configure jQuery to retry ajax calls if they fail

我在自定义JS文件中拥有所有的ajax调用。 相信我有很多他们!
我想在所有ajax调用中实现"重试失败行为"。

有没有办法像"拦截"那样做? 或者我必须一个接一个地做?

我担心的是,未来的开发者将忘记制定重试政策......

示例ajax调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$.ajax({
    url: apiRoot + 'reservationItens?reservaId=' + idReservation + '&bagId=' + idBag,
    type: 'PUT',
    success: function () {
        if (onSuccess != null) {
            onSuccess();
        }
    },
    error: function (x, y, z) {
        if (onError != null) {
            onError(x, y, z);
        }
    }
});


您可以使用ajaxError进行每次ajax错误调用的回调。
此外,您可以向设置对象添加一个布尔值,并在回调中检查它,以确保一个失败的请求仅被第二次调用而不是更多。

1
2
3
4
5
6
$(document).ajaxError(function (event, jqxhr, settings) {
    if(!settings.secondExec) {
        settings.secondExec = true;
        $.ajax(settings);
    }
});

如果需要,为第二个请求添加超时,以增加同时解决随机服务器或连接问题的可能性:

1
2
3
setTimeout(function() {
    $.ajax(settings);
}, 500);

如果要排除某些请求,只需将另一个属性添加到请求设置中,然后在示例中使用secondExec


这是一个有效的jsfiddle。

我会这样做,具有递归功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function AjaxRetry(settings, maxTries, interval) {
    var self = this;
    this.settings = settings;
    this.maxTries = typeof maxTries ==="number" ? maxTries : 0;
    this.completedTries = 0;
    this.interval = typeof interval ==="number" ? interval : 0;

    // Return a promise, so that you can chain methods
    // as you would with regular jQuery ajax calls
    return tryAjax().promise();

    function tryAjax(deferred) {
        console.log("Trying ajax #" + (self.completedTries + 1));
        var d = deferred || $.Deferred();
        $.ajax(self.settings)
            .done(function(data) {
                // If it succeeds, don't keep retrying
                d.resolve(data);
            })
            .fail(function(error) {
                self.completedTries++;

                // Recursively call this function again (after a timeout)
                // until either it succeeds or we hit the max number of tries
                if (self.completedTries < self.maxTries) {
                    console.log("Waiting" + interval +"ms before retrying...");
                    setTimeout(function(){
                        tryAjax(d);
                    }, self.interval);
                } else {
                    d.reject(error);
                }
            });
        return d;
    }
}

然后使用是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 var settings = {
     url:"https://httpbin.org/get",
     data: {foo:"bar"},
     contentType:"application/json; charset=UTF-8"
 };
 var maxTries = 3;
 var interval = 500;

 // Make your ajax call and retry up to 3 times,
 // waiting 500 milliseconds between attempts.
 new AjaxRetry(settings, maxTries, interval)
    .done(function(data){
        alert("My ajax call succeeded!");
    })
    .fail(function(error) {
        alert("My ajax call failed :'(");
    })
    .always(function(resp){
        alert("My ajax call is over.");
    });


您可以为ajax调用创建api方法,就像这个一样。在ajaxApi函数中,您可以创建自己的处理程序。例如,对于成功或错误事件,感谢这个开发人员使用这个api可以附加他的处理程序,而不用担心附加什么处理程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function outerSuccesFN() {
    console.log('outerSuccesFN');
}

function outerErroFN() {
    console.log('outerErroFN');
}

function completeFn() {
    console.log(completeFn);
}

function ajaxApi(url, dataType, data, timeout) {

    var ajaxResults = $.ajax({
        url: url,
        dataType: dataType,
        data: data,
        timeout: timeout
    });

    function mySuccesFn() {
        console.log('mySuccesFn');
    }

    function myErroFn() {
        console.log('myErroFn');
    }

    return ajaxResults.done(mySuccesFn).fail(myErroFn);
}

var ajaxResult = ajaxApi('http://api.jquery.com/jsonp/', 'jsonp', {
    title: 'ajax'
}, 15000);

ajaxResult.done(outerSuccesFN).fail(outerErroFN).always(completeFn);