116

擬似コード:

$(document).ajaxError(function(e, xhr, options, error) {
  xhr.retry()
})

さらに良いのは、ある種の指数バックオフです

4

8 に答える 8

263

このようなもの:


$.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
        }
    }
});
于 2012-04-05T07:44:22.667 に答える
17

1 つのアプローチは、ラッパー関数を使用することです。

(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);

別のアプローチは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);
}

別の方法 ( 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') 
});

考慮すべき点は、同じコードが 2 回実行されるのを避けるために、メソッドが以前にラップされていないことを確認することです。$.ajax


これらのスニペットを(そのまま)コピーしてコンソールに貼り付けてテストできます

于 2016-10-01T23:17:35.633 に答える
7

以下のコードで多くの成功を収めました (例: 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 );
        });
}
于 2012-08-25T09:37:25.220 に答える
0

このための小さなプラグインを次に示します。

https://github.com/execjosh/jquery-ajax-retry

自動インクリメントタイムアウトは、それに追加するのに適しています。

グローバルに使用するには、$.ajax 署名で独自の関数を作成し、そこで API を再試行して、すべての $.ajax 呼び出しを新しい関数に置き換えます。

また、$.ajax を直接置き換えることもできますが、再試行せずに xhr 呼び出しを行うことはできません。

于 2013-05-23T13:10:35.853 に答える
0

エラー関数の this が Window を指しているため、DemoUsers の回答は Zepto では機能しません。(そして、「this」を使用する方法は、それらが ajax をどのように実装しているか、またはその必要がないかを知らないため、十分に安全ではありません。)

Zepto の場合は、以下を試すことができますが、今のところうまくいきます。

var AjaxRetry = function(retryLimit) {
  this.retryLimit = typeof retryLimit === 'number' ? retryLimit : 0;
  this.tryCount = 0;
  this.params = null;
};
AjaxRetry.prototype.request = function(params, errorCallback) {
  this.tryCount = 0;
  var self = this;
  params.error = function(xhr, textStatus, error) {
    if (textStatus === 'timeout') {
      self.tryCount ++;
      if (self.tryCount <= self.retryLimit) {
        $.ajax(self.params)      
        return;
      }
    }
    errorCallback && errorCallback(xhr, textStatus, error);
  };
  this.params = params;
  $.ajax(this.params);
};
//send an ajax request
new AjaxRetry(2).request(params, function(){});

コンストラクターを使用して、リクエストが再入可能であることを確認してください。

于 2016-05-25T09:37:34.847 に答える
0

ライブラリの非同期ロードで私のために働いた方法は次のとおりです。

var jqOnError = function(xhr, textStatus, errorThrown ) {
    if (typeof this.tryCount !== "number") {
      this.tryCount = 1;
    }
    if (textStatus === 'timeout') {
      if (this.tryCount < 3) {  /* hardcoded number */
        this.tryCount++;
        //try again
        $.ajax(this);
        return;
      }
      return;
    }
    if (xhr.status === 500) {
        //handle error
    } else {
        //handle error
    }
};

jQuery.loadScript = function (name, url, callback) {
  if(jQuery[name]){
    callback;
  } else {
    jQuery.ajax({
      name: name,
      url: url,
      dataType: 'script',
      success: callback,
      async: true,
      timeout: 5000, /* hardcoded number (5 sec) */
      error : jqOnError
    });
  }
}

次に.load_script、アプリから呼び出して、成功のコールバックをネストします。

$.loadScript('maps', '//maps.google.com/maps/api/js?v=3.23&libraries=geometry&libraries=places&language=&hl=&region=', function(){
    initialize_map();
    loadListeners();
});
于 2016-03-09T00:36:01.713 に答える