Sözde kod:
$(document).ajaxError(function(e, xhr, options, error) {
xhr.retry()
})
Daha da iyisi, bir tür üstel geri çekilme olurdu
Sözde kod:
$(document).ajaxError(function(e, xhr, options, error) {
xhr.retry()
})
Daha da iyisi, bir tür üstel geri çekilme olurdu
Yanıtlar:
Bunun gibi bir şey:
$.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
}
}
});
.success
Bu ajax isteğini döndüren işlevi çağırmaya benzer başka bir geri arama işleyicisi eklenmişse bu çalışacak mı?
tryCount
ve retryLimit
aşırı. Yalnızca 1 değişken kullanmayı düşünün:this.retryLimit--; if (this.retryLimit) { ... $.ajax(this) ... }
(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
mülkü kullanmaktır .$.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);
}
$.ajax
(KURU için daha iyi)// 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')
});
Bir nokta yapıyor düşünün emin$.ajax
iki kez çalıştıran aynı kod önlemek için, yöntem zaten önceden sarılmış değildi.
Bu snippet'leri (olduğu gibi) test etmek için konsola kopyalayıp yapıştırabilirsiniz.
Aşağıdaki kodla çok başarılı oldum (örnek: 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 );
});
}
Biri ararsa bu cevapların hiçbiri işe yaramaz .done()
ajax çağrısından sonra çünkü gelecekteki geri aramaya eklemek için başarı yöntemine sahip olmayacaksınız. Yani biri bunu yaparsa:
$.ajax({...someoptions...}).done(mySuccessFunc);
Sonra mySuccessFunc
tekrar denemede aranmayacak. İşte benim çözümüm, buradaki @ cjpak'ın cevabından büyük ölçüde ödünç alınmış . Benim durumumda, AWS'nin API Gateway'i 502 hatasıyla yanıt verdiğinde yeniden denemek istiyorum.
const RETRY_WAIT = [10 * 1000, 5 * 1000, 2 * 1000];
// This is what tells JQuery to retry $.ajax requests
// Ideas for this borrowed from https://stackoverflow.com/a/12446363/491553
$.ajaxPrefilter(function(opts, originalOpts, jqXHR) {
if(opts.retryCount === undefined) {
opts.retryCount = 3;
}
// Our own deferred object to handle done/fail callbacks
let dfd = $.Deferred();
// If the request works, return normally
jqXHR.done(dfd.resolve);
// If the request fails, retry a few times, yet still resolve
jqXHR.fail((xhr, textStatus, errorThrown) => {
console.log("Caught error: " + JSON.stringify(xhr) + ", textStatus: " + textStatus + ", errorThrown: " + errorThrown);
if (xhr && xhr.readyState === 0 && xhr.status === 0 && xhr.statusText === "error") {
// API Gateway gave up. Let's retry.
if (opts.retryCount-- > 0) {
let retryWait = RETRY_WAIT[opts.retryCount];
console.log("Retrying after waiting " + retryWait + " ms...");
setTimeout(() => {
// Retry with a copied originalOpts with retryCount.
let newOpts = $.extend({}, originalOpts, {
retryCount: opts.retryCount
});
$.ajax(newOpts).done(dfd.resolve);
}, retryWait);
} else {
alert("Cannot reach the server. Please check your internet connection and then try again.");
}
} else {
defaultFailFunction(xhr, textStatus, errorThrown); // or you could call dfd.reject if your users call $.ajax().fail()
}
});
// NOW override the jqXHR's promise functions with our deferred
return dfd.promise(jqXHR);
});
Bu pasaj 2 saniye, ardından 5 saniye, ardından 10 saniye sonra geri çekilecek ve yeniden deneyecek ve bunu RETRY_WAIT sabitini değiştirerek düzenleyebilirsiniz.
AWS desteği, mavi ayda yalnızca bir kez gerçekleştiği için yeniden deneme eklememizi önerdi.
İşte bunun için küçük bir eklenti:
https://github.com/execjosh/jquery-ajax-retry
Otomatik artan zaman aşımı buna iyi bir katkı olacaktır.
Global olarak kullanmak için $ .ajax imzasıyla kendi işlevinizi oluşturun, orada api'yi tekrar deneyin ve tüm $ .ajax çağrılarınızı yeni işlevinizle değiştirin.
Ayrıca doğrudan $ .ajax'ın yerine de geçebilirsiniz, ancak o zaman yeniden denemeden xhr çağrıları yapamazsınız.
Kitaplıkların eşzamansız yüklenmesi için benim için çalışan yöntem şu şekildedir:
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
});
}
}
Ardından .load_script
uygulamanızdan arayın ve başarı geri aramalarınızı yerleştirin:
$.loadScript('maps', '//maps.google.com/maps/api/js?v=3.23&libraries=geometry&libraries=places&language=&hl=®ion=', function(){
initialize_map();
loadListeners();
});
DemoUsers'ın cevabı Zepto ile çalışmıyor, çünkü bu hata fonksiyonunda Pencereyi gösteriyor. (Ve ajax'ı nasıl uyguladıklarını bilmediğiniz veya buna gerek olmadığı için 'bunu' kullanmanın bu yolu yeterince güvenli değildir.)
Zepto için, belki aşağıda deneyebilirsiniz, şimdiye kadar benim için iyi çalışıyor:
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(){});
İsteğin evresel olduğundan emin olmak için yapıcıyı kullanın!
Kodunuz neredeyse dolu :)
const counter = 0;
$(document).ajaxSuccess(function ( event, xhr, settings ) {
counter = 0;
}).ajaxError(function ( event, jqxhr, settings, thrownError ) {
if (counter === 0 /*any thing else you want to check ie && jqxhr.status === 401*/) {
++counter;
$.ajax(settings);
}
});
tries
işlevden çağırırsanız, ona bir parametre verebilir ve başarısız olursa işlevinizi çağırırsınıztries+1
. Yürütmeyitries==3
veya başka bir numarayı durdurun .