使用jQuery在失败时重试AJAX请求的最佳方法是什么?

Tom*_*man 92 javascript ajax jquery xmlhttprequest

伪代码:

$(document).ajaxError(function(e, xhr, options, error) {
  xhr.retry()
})
Run Code Online (Sandbox Code Playgroud)

更好的是某种指数回退

Sud*_*oti 215

像这样的东西:


$.ajax({
    url : 'someurl',
    type : 'POST',
    data :  ....,   
    tryCount : 0,
    retryLimit : 3,
    success : function(json) {
        //do something
    },
    error : function(xhr, textStatus, errorThrown ) {
        if (textStatus == 'timeout') {
            this.tryCount++;
            if (this.tryCount <= this.retryLimit) {
                //try again
                $.ajax(this);
                return;
            }            
            return;
        }
        if (xhr.status == 500) {
            //handle error
        } else {
            //handle error
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 一对`tryCount`和`retryLimit`过多.考虑只使用1个变量:`this.retryLimit--; if(this.retryLimit){... $ .ajax(this)...}` (13认同)
  • 我采用了@ Sudhir的解决方案并在github上创建了一个$ .retryAjax插件:https://github.com/mberkom/jQuery.retryAjax (12认同)
  • 这不适合我.条件中的this.tryCount始终为1. (2认同)
  • @MichaelBerkompas - 你的插件还能运作吗?它未在2年内收到提交. (2认同)
  • 如果附加了另一个回调处理程序如`.success`来调用返回此ajax请求的函数,这会工作吗? (2认同)
  • 惊人的!我添加了额外的参数 `timeout : 3000`,然后每次重试都会增加超时时间:`this.timeout = this.timeout * this.tryCount;` 也许它可能会给任何请求提供更多时间来返回响应. (2认同)

vsy*_*ync 11

一种方法是使用包装函数:

(function runAjax(retries, delay){
  delay = delay || 1000;
  $.ajax({
    type        : 'GET',
    url         : '',
    dataType    : 'json',
    contentType : 'application/json'
  })
  .fail(function(){
    console.log(retries); // prrint retry count
    retries > 0 && setTimeout(function(){
        runAjax(--retries);
    },delay);
  })
})(3, 100);
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用一个retries属性$.ajax

// define ajax settings
var ajaxSettings = {
  type        : 'GET',
  url         : '',
  dataType    : 'json',
  contentType : 'application/json',
  retries     : 3  //                 <-----------------------
};

// run initial ajax
$.ajax(ajaxSettings).fail(onFail)

// on fail, retry by creating a new Ajax deferred
function onFail(){
  if( ajaxSettings.retries-- > 0 )
    setTimeout(function(){
        $.ajax(ajaxSettings).fail(onFail);
    }, 1000);
}
Run Code Online (Sandbox Code Playgroud)

另一种方式(GIST) - 覆盖原始$.ajax(更好的DRY)

// enhance the original "$.ajax" with a retry mechanism 
$.ajax = (($oldAjax) => {
  // on fail, retry by creating a new Ajax deferred
  function check(a,b,c){
    var shouldRetry = b != 'success' && b != 'parsererror';
    if( shouldRetry && --this.retries > 0 )
      setTimeout(() => { $.ajax(this) }, this.retryInterval || 100);
  }

  return settings => $oldAjax(settings).always(check)
})($.ajax);



// now we can use the "retries" property if we need to retry on fail
$.ajax({
    type          : 'GET',
    url           : 'http://www.whatever123.gov',
    timeout       : 2000,
    retries       : 3,     //       <-------- Optional
    retryInterval : 2000   //       <-------- Optional
})
// Problem: "fail" will only be called once, and not for each retry
.fail(()=>{
  console.log('failed') 
});
Run Code Online (Sandbox Code Playgroud)

需要考虑的一点是确保$.ajax方法之前尚未包装,以避免相同的代码运行两次.


您可以将这些代码段(按原样)复制粘贴到控制台以进行测试


Nab*_*imi 5

我在下面的代码中取得了很多成功(例如:http : //jsfiddle.net/uZSFK/

$.ajaxSetup({
    timeout: 3000, 
    retryAfter:7000
});

function func( param ){
    $.ajax( 'http://www.example.com/' )
        .success( function() {
            console.log( 'Ajax request worked' );
        })
        .error(function() {
            console.log( 'Ajax request failed...' );
            setTimeout ( function(){ func( param ) }, $.ajaxSetup().retryAfter );
        });
}
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个无限循环吗?鉴于问题有一个retryLimit,显然是想迎合服务器永不回来的问题……我认为这确实必须存在 (5认同)
  • 我建议的唯一更改是用function(){func(param)}替换'func(“'+ param”'“)'。这样,您可以直接传递参数而无需将其转换为字符串并返回,这很容易失败! (4认同)
  • jQuery.ajaxSetup()说明:为将来的Ajax请求设置默认值。不建议使用它。http://api.jquery.com/jQuery.ajaxSetup/ (3认同)