Question

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?

Was it helpful?

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)
    

OTHER TIPS

Well you might clone the object using jQuery and then restart your call when the browser goes back online

// Deep copy
var savedXhr= jQuery.extend(true, {}, xhr);

don't know if this really works, you could try it

EDIT - Ok i tried it and no way, you can't call send() on that object. This is because xhr is not the original request but a 'fake' object created by jQuery A different approach might be this one: You save the settings object and then you start another $.ajax call with those settings. Basically you do

var settingsSaved;

$(document).ajaxSend(function(event, xhr, settings, response) {
    if (!navigator.onLine) {
        settingsSaved = jQuery.extend(true, {}, settings);
        xhr.abort();
    } else {
        //Send the request with the old settings
        $.ajax(settingsSaved);
        //abort the new request
        xhr.abort();
    }
}

Be really careful that this requre an accurate flow control because every time you call $.ajax you trigger another ajaxSend event...maybe you could simply start off a new XMLHTTPRequest using the values from the settingsSaved object.

Look at this fiddle, the first time you click a button, the call is aborted. The second time the call starts with the old settings and from then on all requests are normal

http://jsfiddle.net/hFmWX/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top