Search code examples
jqueryajaxnavigator

restart Ajax Request based on the jquery xhr object after Event: navigator.onLine


We are binding global ajax handlers to check if the browser went offline :

$(document).ajaxSend(function(event, xhr, settings, response){  
   if(!navigator.onLine){  
        xhr.abort();  
   }  
}

then we are showing a dialog to the user that the browser went offline and bind for the 'online' event to hide the dialog when the browser turns online again.

Is there Anyway (even a hacky one) to restart the Ajax request based on the old which fits in the old context?


Solution

  • Here's the cleanest approach I can think of:

    1. A queue for caching AJAX request settings so each subsequent call doesn't overwrite the previous one
    2. A conditional in the ajaxSend() handler that either pushes the calls on the queue for later or executes the entire queue.

      !(function($, window, undefined){
          var ajaxRequestQueue  = [],    // queue for requests that were made while offline
              isProcessingQueue = false;
      
          function processRequestQueue() {
              if (isProcessingQueue === true)
              {
                  return;
              }
      
              isProcessingQueue = true;
              while (settings = ajaxRequestQueue.shift())
              {
                  $.ajax(settings);
              }
              isProcessingQueue = false;
          }
      
          $(document).ajaxSend(function(event, xhr, settings, response){
              if (!navigator.onLine) {
                  // abort the original request
                  xhr.abort();
                  // push a copy of the request's settings on the queue
                  ajaxRequestQueue.push($.extend(true, {}, settings));
              }
              else if (ajaxRequestQueue.length > 0
                   && isProcessingQueue        === false)
              // there are calls on queue and we haven't triggered 'ajaxSend' ourselves
              {
                  processRequestQueue();
              }
          });
      
          // Bind to start processing the queue when the browser comes back online
          window.addEventListener("online", processRequestQueue);
      })(jQuery, window)