关于javascript:如何重新发送失败的ajax请求?

How do I resend a failed ajax request?

我有多个Ajax请求,一些请求数据每分钟都由用户通过一个UI启动。

1
2
3
$.get('/myurl', data).done(function( data ){
   // do stuff..
});

由于身份验证失败,请求可能失败。我已经设置了一个全局.ajaxError()方法来捕获任何失败的请求。

1
2
3
$(document).ajaxError(function( e, jqxhr ){
   // Correct error..
});

捕捉到错误后,我重置授权。重置授权可以工作,但用户必须手动重新启动Ajax调用(通过UI)。

如何使用最初发送的jqxhr重新发送失败的请求?

(我正在使用jquery for the Ajax)


找到了这个建议这个问题很好解决的帖子。

主要的事情是使用$.Ajaxprefilter并用一个自定义的错误处理程序替换错误处理程序,该程序检查重试情况,并使用闭包的"originalOptions"执行重试。

我正在发布代码,以防将来它离线。同样,信用证属于原作者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// register AJAX prefilter : options, original options
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {

   originalOptions._error = originalOptions.error;

   // overwrite error handler for current request
   options.error = function( _jqXHR, _textStatus, _errorThrown ){

   if (... it should not retry ...){

         if( originalOptions._error ) originalOptions._error( _jqXHR, _textStatus, _errorThrown );
         return;
      };

      // else... Call AJAX again with original options
      $.ajax( originalOptions);
   };
});


在这种情况下,我将为403状态代码编写一个特定的处理程序,这意味着未经授权(我的服务器也将返回403)。从jQueryAjax文档中,您可以

1
2
3
4
5
6
7
$.ajax({
  statusCode: {
    403: function() {
        relogin(onSuccess);
    }
  }
});

为了达到这个目的。

在这个处理程序中,我将调用relogin方法,传递一个函数,该函数捕获登录成功时要做的事情。在这种情况下,可以传入包含要再次运行的调用的方法。

在上面的代码中,relogin应该调用登录代码,onSuccess应该是一个函数,它包装了您每分钟执行的代码。

编辑-根据您在评论中的澄清,这种情况发生在多个请求中,我个人会为您的应用程序创建一个API,它捕获与服务器的交互。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
app = {};
app.api = {};
// now define all your requests AND request callbacks, that way you can reuse them
app.api.makeRequest1 = function(..){..} // make request 1
app.api._request1Success = function(...){...}// success handler for request 1
app.api._request1Fail = function(...){...}// general fail handler for request 1

/**
  A method that will construct a function that is intended to be executed
  on auth failure.

  @param attempted The method you were trying to execute
  @param args      The args you want to pass to the method on retry
  @return function A function that will retry the attempted method
**/

app.api.generalAuthFail = function(attempted, args){
   return function(paramsForFail){ // whatever jquery returns on fail should be the args
      if (attempted) attempted(args);
   }  
}

所以有了这个结构,在你的request1方法中,你会做一些类似的事情

1
2
3
4
5
6
$().ajax({
    ....
    statusCode: {
        403: app.api.generalAuthFail(app.api.request1, someArgs);
    }
}}

generalAuthFailure将返回一个回调,该回调执行您传入的方法。


下面的代码将保留原始请求,并将尝试成功3次。

1
2
3
4
5
6
7
var tries = 0;
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
    if(tries < 3){
        tries++;
        $.ajax(this).done(function(){tries=0;});
    }
});


您可以选择命名每个函数,然后按照hvgotcodes的答案调用它们。

在扩展默认值时,可以使用可重用函数设置请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function getRequest( options ){

    var // always get json
        defaults = { dataType: 'json' },
        settings = $.extend( defaults, options );


    return // send initial ajax, if it's all good return the jqxhr object
           $.ajax( settings )
           // on error
           .fail(function( jqxhr, e ){
                // if the users autherization has failed out server responds with a 401
                if( jqxhr.status === 401 ){
                    // Authenticate user again
                    resetAuthentication()
                    .done(function(){
                        // resend original ajax also triggering initial callback
                        $.ajax( settings );
                    });
                }
           });
};

要使用上述函数,您需要编写如下内容:

1
2
3
4
5
getRequest({
    url: 'http://www.example.com/auth.php',
    data: {user: 'Mike', pass: '12345'},
    success: function(){ // do stuff }
});

getRequest()可能会被递归和/或转换成jquery插件,但这足以满足我的需要。

注意:如果重置函数可能失败,那么getRequest()必须是递归的。