I use the following code to retry operations that return HTTP 502, 503 or 504:
/**
* @function RetryDelayFunction
* Returns the amount of time to wait after a failure.
*
* @param {Number} retries the number of times the operation has been retried
* @return {Number} the number of milliseconds to wait before retrying the operation
*/
/**
* @typedef {Object} RetryAjaxOptions
*
* @property {Number} retries the number of times to retry a failed operation
* @param {RetryDelayFunction} delayFunction maps a failure count to a delay in milliseconds
* @param {Array} errorCodes the HTTP response codes that should trigger a retry
*/
/**
* Retries HTTP requests using an exponential back-off in case of HTTP 502, 503, 504. Based on
* https://github.com/execjosh/jquery-ajax-retry and http://javadoc.google-http-java-client.googlecode.com/hg/1.15.0-rc/com/google/api/client/util/ExponentialBackOff.html
*
* The $.ajax() settings object must contain a {@code retry} key to enable this functionality.
* This object is of type {@link RetryAjaxOptions} and may be used to override the default behavior.
*/
function installAjaxRetries()
{
"use strict";
/**
* Do nothing.
*/
var noOpFunction = function()
{
};
var delayInitialIntervalMs = 250;
var delayIntervalMultiplier = 1.5;
var delayRandomizationFactor = 0.5;
/**
* @function RetryDelayFunction
*/
var defaultDelayFunction = function(retries)
{
var retryInterval = delayInitialIntervalMs * Math.pow(delayIntervalMultiplier, retries);
var delta = retryInterval * delayRandomizationFactor;
var min = retryInterval - delta;
var max = retryInterval + delta;
return (Math.random() * (max - min + 1)) + min;
};
var MIN_RETRIES = 1;
var DEFAULT_RETRIES = 3;
var DEFAULT_ERROR_CODES = [502, 503, 504];
var DEFAULT_OPTIONS =
{
retries: DEFAULT_RETRIES,
delayFunction: defaultDelayFunction,
errorCodes: DEFAULT_ERROR_CODES
};
var originalAjaxFunction = $.ajax;
var ajaxWithRetry = function(settings)
{
settings = $.extend(true, {}, $.ajaxSettings, settings);
if (!settings.retry)
return originalAjaxFunction(settings);
var retries = 0;
var options = $.extend(true, {}, $.ajaxRetrySettings, settings.retry);
var originalErrorFunction = settings.error || noOpFunction;
var originalCompleteFunction = settings.complete || noOpFunction;
// Clamp options
options.retries = Math.max(MIN_RETRIES, options.retries);
options.delayFunction = options.delayFunction || defaultDelayFunction;
// Override error function
settings.error = function(xhr, textStatus, errorThrown)
{
if ($.inArray(xhr.status, options.errorCodes) < 0 || retries >= options.retries)
{
// Give up and call the original error() function
originalErrorFunction.call(this, xhr, textStatus, errorThrown);
return;
}
// The complete() handler will retry the operation
};
// Override complete function
settings.complete = function(xhr, textStatus)
{
if ($.inArray(xhr.status, options.errorCodes) < 0 || retries >= options.retries)
{
// Give up and call the original complete() function
originalCompleteFunction.call(this, xhr, textStatus);
return;
}
var delayMs = options.delayFunction(retries);
++retries;
window.setTimeout(function()
{
originalAjaxFunction(settings);
}, delayMs);
};
originalAjaxFunction(settings);
return settings.xhr;
};
var ajaxRetrySetup = function(options)
{
DEFAULT_OPTIONS = $.extend(true, DEFAULT_OPTIONS, options);
$.ajaxRetrySettings = DEFAULT_OPTIONS;
return DEFAULT_OPTIONS;
};
$.ajaxRetrySettings = DEFAULT_OPTIONS;
$.ajaxRetrySetup = ajaxRetrySetup;
$.ajax = ajaxWithRetry;
}
installAjaxRetries();
Ever since I started using this code, some AJAX calls began returning HTTP 200 with an empty responseText. What's weird is that first request is failing (no retrying is actually taking place) and simply commenting out the code that overrides settings.complete
fixes the problem. I am using Chrome 29.0.1547.57 m.
Why does overriding settings.complete
cause this problem?
UPDATE: I control the server, so I know for a fact it never returns HTTP 200 with an empty response.
UPDATE2: I can no longer reproduce the problem and I don't recall what I did to fix it. If I can't reproduce it in the next couple of months I plan on closing it.
may be you are trying cross domain server.set response header to allow-access-origin
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With