当前位置: 首页 > 面试题库 >

重试一个jquery ajax请求,该请求的延迟中附加了回调

秦才
2023-03-14
问题内容

我正在尝试实现一个重试由于临时原因而失败的ajax请求的系统。在我的情况下,这是关于重试失败的请求,该请求带有401状态代码,因为会话已过期,然后调用了刷新会话的刷新Web服务。

问题在于成功完成重试后不会调用“完成”回调,这与调用“成功” 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拒绝的请求排队,并在成功调用/ refresh之后重试它们。

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包装在另一个延迟的对象中。

我在上面的示例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({}, originalOpts, {
                        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上的所有“承诺方法”。

注意: 对于任何其他发现此问题的人,如果您在ajax选项中使用success:和附加回调error:,则此代码段将 无法
按您期望的方式工作。假定唯一的回调是使用jqXHR 的.done(callback).fail(callback)方法附加的回调。



 类似资料:
  • Flask 的设计原则中有一条是响应对象被创建并在一条可能的回调链中传递,而在 这条回调链但中的任意一个回调,您都可以修改或者替换掉他们。当请求开始被 处理时,还没有响应对象,响应对象将在这一过程中,被某个视图函数或者系统 的其他组件按照实际需要来闯将。 但是,如果您想在响应过程的结尾修改响应对象,但是这是对象还不存在,那么会发生 什么呢?一个常见的例子是您可能需要在 before-request

  • 我正在尝试使用JQuery在Ajax中向请求添加头。 以下是代码:- 然后我使用了要求(要求是chrome火狐插件,我们可以手动添加一个标题到请求)。 手动添加标题后:- 在这两个pics请求头中,“ACCESS-CONTROL-request-HEADERS”中都有x-auth-token,但第二个pic中有“x-auth-token”头和头值,而第一个pic中没有。 所以我的问题是如何使用JQ

  • 问题内容: 我有一个jQuery Ajax请求,我想用文本输入调用它,因此我将其嵌套在里面。这很好。 但这有时表现为越野车。当我非常快速地输入一些文本时,我得到的输入单词的结果中省略了原始输入单词的最后几个字母(可能是浏览器的某些错误)。我希望在没有输入活动持续一秒钟的情况下发送ajax请求,如果我很快输入文本并休息一秒钟(意味着我进行了输入)。我怎样才能做到这一点? 问题答案: 听起来好像是从先

  • 我正在使用Spring5WebClient从RESTAPI重复获取运行进程的某些状态。 在这里的帮助下,我现在找到了这个解决方案: 在这种情况下,get请求以非常高的速率触发。什么是正确的方法来限制请求速率,让我们说每秒1个请求? 我尝试使用,但这只会延迟结果,而不会延迟请求本身。

  • 我正在使用谷歌地图api获取城市之间的距离,获取这些距离后,我想将它们存储在数组中。但是谷歌api不允许无延迟请求。我如何添加延迟。或者有没有其他方法可以获得驾驶距离。这是代码 以上代码在没有循环的情况下运行良好。

  • 测试结构: Thread1-Sampler1(例如:访问登录表单) 我试着把计时器当作取样器,不管是父母还是孩子。也许我错过了什么,因为没有一个计时器在为我工作。 我已经找到了类似的问题解决方案,但没有一个对我有用:JMeter——在多个线程组之间共享请求之间的延迟Ultimate thread Group中每个线程的延迟