What's the best way to retry an AJAX request on failure using jQuery?
Something like this:
$.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 } }});
One approach is to use a wrapper function:
(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);
Another approach would be to use a retries
property on the $.ajax
// define ajax settingsvar 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 deferredfunction onFail(){ if( ajaxSettings.retries-- > 0 ) setTimeout(function(){ $.ajax(ajaxSettings).fail(onFail); }, 1000);}
Another way (GIST) - override original $.ajax
(better for 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') });
A point to consider is making sure the $.ajax
method wasn't already wrapped previously, in order to avoid the same code running twice.
You can copy-paste these snippets (as-is) to the console to test them
I've had a lot of success with this code below (example: 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 ); });}