重试失败的jQuery.ajax请求

时间:2013-06-27 17:02:24

标签: jquery jquery-deferred

我需要创建一个重试失败的ajax请求的函数,直到给定的限制,但是我需要确保只有在超过最大重试次数时拒绝承诺,如下所示:

function my_ajax(...) { ... }

// then I use it this way
return $.when(my_ajax('foo.json'), my_ajax('bar.json'))

为了使用jQuery.when,只应返回my_ajax的一个promise,这应该在解析内部jQuery.ajax时解析,并且只在最大重试次数时才被拒绝。 / p>

我制作的代码是:

function do_ajax(args, dfd, attempt) {
    dfd     || (dfd = $.Deferred());
    attempt || (attempt = 1);

    $.ajax(args).then(dfd.resolve, function(xhr, text_status, error_thrown) {
        console.error(/* something useful */);
        attempt++;

        if(attempt > 3) {
            dfd.reject(xhr, text_status, error_thrown);
        } else {
            do_ajax(args, dfd, attempt);
        }
    });

    return dfd.promise();
}

// in some random code
return $.when(do_ajax({url:'foo.json'}), do_ajax({url:'bar.json'});

这对我有用*,但有点难以理解。问题是:有没有更好(更容易阅读)的方法呢?

* - 实际上我有时候没有测试失败,但是当第一个ajax请求成功时我工作正常。

2 个答案:

答案 0 :(得分:3)

我认为您的代码是正确的方法,将您的调用包装在新的Deferred中并返回,直到达到所有尝试。

您可以尝试在匿名函数中包含递归调用,以提高可读性。

我是这样写的:

function doAjax(ajaxArgs, attempt) {
    // the wrapped returned dfd
    var wrappedDfd = $.Deferred();

    // your nested call using attempt counter
    (function nestedCall() {
        // if call succed, resolve the wrapped dfd
        $.ajax(ajaxArgs).then(wrappedDfd.resolve, function() {
            // update attempt counter
            attempt--;
            if (attempt > 0) {
                // try another call
                nestedCall();
            } else {
                // max try reached, reject wrapped dfd
                wrappedDfd.reject();
            }
        });
    })();

    return wrappedDfd.promise();
};

这与您的代码非常相似。

这是jsfiddle。出于测试目的,我通过模拟工厂调用替换了doAjax参数,但代码保持不变。

希望得到这个帮助。

答案 1 :(得分:1)

根据Mordhak的答案和SO dherman周围的其他几个人创建了一个jQuery插件:jquery.ajaxRetryGitHub repo),johnkpaul 也是如此:jquery.ajax-retry

<强> jquery.ajaxRetry

实施例

$.ajax({
  // Retry this request up to 2 times
  shouldRetry: 2
});
  • 可以无限期重试
  • 可以重试n
  • 可以运行某个功能并评估true中的falseshouldRetry以确定是否应继续重试

<强> jquery.ajax重试

实施例

$.ajax(options).retry({times:3, timeout:3000}).then(function(){
    alert("success!");
  }); 
  • 可以重试n
  • 可以指定重试之间等待的时间
  • 可以指定要重试的状态代码