重试一个jquery ajax请求,该请求具有附加到其延迟的回调

前端之家收集整理的这篇文章主要介绍了重试一个jquery ajax请求,该请求具有附加到其延迟的回调前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图实现一个系统重试ajax请求失败的临时原因。在我的情况下,它是关于重试请求失败的401状态代码,因为会话已过期,在调用刷新webservice恢复会话后。

问题是,“done”回调不会在成功的重试上调用,与调用的“success”ajax选项回调不同。我已经做了一个简单的例子如下:

$.ajaxSetup({statusCode: {
    404: function() {
        this.url = '/existent_url';
        $.ajax(this);
    }
}});

$.ajax({
    url: '/inexistent_url',success: function() { alert('success'); }
})
.done(function() {
    alert('done');
});

有没有一种方法来完成样式的回调调用成功的重试?我知道一个推迟的人在“被拒绝”之后不能被“解决”,是否有可能防止被拒绝?或者也许复制原始延迟的doneList到新的延迟?我的想法:)

一个更现实的示例如下,其中我试图排队所有401拒绝的请求,并在成功调用/刷新后重试它们。

var refreshRequest = null,waitingRequests = null;

var expiredTokenHandler = function(xhr,textStatus,errorThrown) {

    //only the first rejected request will fire up the /refresh call
    if(!refreshRequest) {
        waitingRequests = $.Deferred();
        refreshRequest = $.ajax({
            url: '/refresh',success: function(data) {
                // session refreshed,good
                refreshRequest = null;
                waitingRequests.resolve();
            },error: function(data) {
                // session can't be saved
                waitingRequests.reject();
                alert('Your session has expired. Sorry.');
            }
       });
    }

    // put the current request into the waiting queue
    (function(request) {
        waitingRequests.done(function() {
            // retry the request
            $.ajax(request);
        });
    })(this);
}

$.ajaxSetup({statusCode: {
    401: expiredTokenHandler
}});

机制工作,401失败的请求第二次被触发,问题是他们的“完成”回调没有被调用,所以应用程序停顿。

解决方法

你可以使用 jQuery.ajaxPrefilter将jqXHR包装在另一个 deferred object

我做了一个例子,jsFiddle显示它的工作,并试图适应一些你的代码来处理401到这个版本:

$.ajaxPrefilter(function(opts,originalOpts,jqXHR) {
    // you could pass this option in on a "retry" so that it doesn't
    // get all recursive on you.
    if (opts.refreshRequest) {
        return;
    }

    // our own deferred object to handle done/fail callbacks
    var dfd = $.Deferred();

    // if the request works,return normally
    jqXHR.done(dfd.resolve);

    // if the request fails,do something else
    // yet still resolve
    jqXHR.fail(function() {
        var args = Array.prototype.slice.call(arguments);
        if (jqXHR.status === 401) {
            $.ajax({
                url: '/refresh',refreshRequest: true,error: function() {
                    // session can't be saved
                    alert('Your session has expired. Sorry.');
                    // reject with the original 401 data
                    dfd.rejectWith(jqXHR,args);
                },success: function() {
                    // retry with a copied originalOpts with refreshRequest.
                    var newOpts = $.extend({},{
                        refreshRequest: true
                    });
                    // pass this one on to our deferred pass or fail.
                    $.ajax(newOpts).then(dfd.resolve,dfd.reject);
                }
            });

        } else {
            dfd.rejectWith(jqXHR,args);
        }
    });

    // NOW override the jqXHR's promise functions with our deferred
    return dfd.promise(jqXHR);
});

这是因为deferred.promise(object)实际上会覆盖jqXHR上的所有“promise方法”。

注意:任何人发现这一点,如果你附加回调成功:和错误:在ajax选项,这个片段将无法按预期的方式工作。它假定唯一的回调是使用jqXHR的.done(callback)和.fail(callback)方法附加的回调。

猜你在找的jQuery相关文章