【问题标题】:Configure jQuery to retry ajax calls if they fail配置 jQuery 以在失败时重试 ajax 调用
【发布时间】:2014-05-14 08:02:07
【问题描述】:

我的所有 ajax 调用都在一个自定义 JS 文件中。相信我,他们有很多! 我想在所有 ajax 调用中实现 "retry on fail behavior"

有没有办法像“拦截”一样做到这一点?还是我必须一件一件的去做?

我担心未来的开发者会忘记设置重试策略...

示例 ajax 调用:

$.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);
        }
    }
});

【问题讨论】:

  • 一些关于为什么拒绝投票/关闭会很好的信息......
  • 不是反对者,但如果您可以添加一个示例来说明您的平均 ajax 调用的样子,那将会很有帮助。
  • 不要使用$.ajax。提供您自己的一套围绕它的 API。
  • 1) 当变量不存在时,onSuccess 和 onError 检查失败。为了使其更稳定,请改用 window.onSuccess 和 window.onError。 2)用英语编程,所以我们都明白你想做什么。 3) 不清楚你的意思或试图做什么。

标签: javascript jquery ajax


【解决方案1】:

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

$(document).ajaxError(function (event, jqxhr, settings) {
    if(!settings.secondExec) {
        settings.secondExec = true;
        $.ajax(settings); 
    }
});

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

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

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

【讨论】:

    【解决方案2】:

    这是working jsfiddle

    我会这样做,使用递归函数:

    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;
        }
    }
    

    然后用法是这样的:

     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.");
        });
    

    【讨论】:

    • 这太棒了!我一直在尝试通过承诺竞赛来实现同样的目标,但这并不是那么清楚。你发这个帖子真的帮助了我。
    • 乐于助人然而。 LMK,如果你想出任何好的改编!
    【解决方案3】:

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

    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);
    

    【讨论】:

    • 使用导出模式可能是值得的,这样您就不会因为只有您关心的方法而使全局命名空间变得混乱。请做。
    猜你喜欢
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    • 2022-01-04
    相关资源
    最近更新 更多