restart Ajax Request based on the jquery xhr object after Event: navigator.onLine
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?
Solution
Here's the cleanest approach I can think of:
- A queue for caching AJAX request settings so each subsequent call doesn't overwrite the previous one
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