在Event:navigator.onLine之后,基于jquery xhr对象重新启动Ajax Request

时间:2012-01-13 10:55:22

标签: jquery ajax navigator

我们正在绑定全局ajax处理程序以检查浏览器是否脱机:

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

然后我们向用户显示一个对话框,说明浏览器脱机并绑定“在线”事件,以便在浏览器再次联机时隐藏对话框。

无论如何(甚至是一个hacky)根据旧的上下文中的旧命令重新启动Ajax请求?

2 个答案:

答案 0 :(得分:2)

您可以使用jQuery克隆该对象,然后在浏览器重新联机时重新启动您的呼叫

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

不知道这是否真的有效,你可以尝试一下

编辑 - 好的我试过了,没办法,你不能在那个对象上调用send()。这是因为xhr不是原始请求,而是由jQuery创建的“假”对象 另一种方法可能就是这样:保存设置对象,然后用另一个$ .ajax调用启动 那些设置。 基本上你做了

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();
    }
}

要非常小心,这需要一个准确的流量控制,因为每次你调用$ .ajax都会触发另一个ajaxSend事件......也许你可以使用来自的值开始一个新的XMLHTTPRequest settingsSaved对象。

看看这个小提琴,第一次点击按钮时,呼叫就会中止。第二次通过旧设置开始通话,从那时起所有请求都是正常的

http://jsfiddle.net/hFmWX/

答案 1 :(得分:2)

这是我能想到的最干净的方法:

  1. 用于缓存AJAX请求设置的队列,以便每次后续调用都不会覆盖前一个
  2. ajaxSend()处理程序中的一个条件,它将队列上的调用推送到以后或执行整个队列。

    !(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)