2013-08-23 19 views
5

używam poniższy kod, żeby ponowić operacje, które zwracają HTTP 502, 503 lub 504:Przeglądarka powrocie HTTP 200 z pustym responseText

/** 
* @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(); 

Odkąd zacząłem używać tego kodu, niektóre rozmowy AJAX zaczęli wracać HTTP 200 z pustym tekstem odpowiedzi. Dziwne jest to, że pierwsze żądanie kończy się niepowodzeniem (w rzeczywistości nie ma miejsca ponowna próba) i po prostu skomentowanie kodu, który przesłania kod settings.complete, rozwiązuje problem. Używam Chrome 29.0.1547.57 m.

Dlaczego przesłanianie settings.complete powoduje ten problem?

UPDATE: Kontroluję serwer, więc wiem, że nigdy nie zwraca HTTP 200 z pustą odpowiedzią.

UPDATE2: Nie mogę już odtworzyć problemu i nie pamiętam, co zrobiłem, aby to naprawić. Jeśli nie uda mi się go odtworzyć w ciągu najbliższych kilku miesięcy, planuję go zamknąć.

+1

HTTP 200 jest standardową odpowiedzią na pomyślne żądania. Tylko FYI. –

+0

@ jimjimmy1995, Rozumiem, ale w tym przypadku kontroluję serwer i nigdy nie zwraca HTTP 200 z pustą odpowiedzią. To nie jest normalne :) – Gili

+0

Czy zarówno jQuery, jak i zakładka Network of Chrome wyświetlają "jQuery" lub "200"? –

Odpowiedz

1

Może to być próbowanie nagłówka odpowiedzi serwera domeny cross.set, aby zezwolić na dostęp-pochodzenie

+0

Nie jest możliwe z dwóch powodów: 1. Wysyłam żądania do tego samego hosta, co plik JS (używając ścieżek względnych, nie określając nazwy hosta). 2. Jeśli tak było, komentowanie 'settings.complete' nie spowodowałoby różnicy. Chciałbym wypróbować 'allow-access-origin', o czym wspomniałeś, ale nie mogę odtworzyć problemu w tej chwili. – Gili

Powiązane problemy