Chrome 中 JQuery 停止和挂起的 ajax 请求

Posted

技术标签:

【中文标题】Chrome 中 JQuery 停止和挂起的 ajax 请求【英文标题】:Stalled and pending ajax requests by JQuery in Chrome 【发布时间】:2015-03-16 14:30:03 【问题描述】:

有时,我的应用程序中的 Ajax 调用(通过 JQuery 1.8)会长时间停留在“待处理”状态(有时长达 17 分钟)。 我用谷歌搜索过,所有可能的解决方案都不起作用:

    我没有安装广告拦截器。 我在 Chrome 中禁用了“预测网络操作以提高页面加载性能”标志。 我还在 Ajax 调用中添加了一个查询字符串以使其唯一(以禁用任何 Chrome 缓存锁定)。

你知道如何解决这个问题吗?

在下面的示例中,请求等待了 17 分钟(通过 Fiddler 验证它仅在 17 分钟后发送)。

   GET http://www.mywebsite.com/foo/rest/publishers/1/packages?_=1421584749323    HTTP/1.1
   Host: www.mywebsite.com
   Connection: keep-alive
   Accept: application/json, text/javascript, */*; q=0.01
   X-Requested-With: XMLHttpRequest
   User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36    (Khtml, like Gecko) Chrome/39.0.2171.99 Safari/537.36
   Content-Type: application/json
   Referer: http://www.mywebsite.com/foo/client/home
   Accept-Encoding: gzip, deflate, sdch
   Accept-Language: en-US,en;q=0.8,he;q=0.6,ru;q=0.4
   Cookie: JSESSIONID=C668509B5AFCDEBE9C9774C4721AFB9D;
   aaassz="ddss"

看图:

【问题讨论】:

你有轮询周期吗?我也有这个问题,因为有很多请求(50 1,5 秒)。所以,chrome 一直等到他们完成,然后才(26 秒后)处理最新的请求,即使它只需要 0.1 秒。 我每 5 分钟有一个轮询周期。但是,我们看不出它如何证明 Chrome 停止 17 分钟是合理的。减少轮询间隔是否解决了您的问题? 根据developer.chrome.com/devtools/docs/…说明,停滞时间是请求在发送之前等待的时间。这个时间包括代理协商所花费的任何时间. 此外,此时间将包括浏览器等待已建立的连接可供重新使用的时间,遵守 Chrome 的每个源规则最多六个 TCP 连接 我在发出请求时收到相同的待处理消息,在我的情况下,我从服务器端接收的数据存在一些问题,我选择了一个新的匿名类型(使用 C# 和 LINQ)而不是整个模型并发送它,它起作用了,但我不知道为什么。 如果您的一项服务未完成请求并发送响应,您最终将导致所有 ajax 请求处于待处理状态。查看第一个为您提供待处理状态的服务。 【参考方案1】:

你可以试试这个。

现已更新为实际工作代码

(使用了我自己的一些时区代码,请原谅对时区的引用)

首先初始化数组并运行你的请求计数逻辑

var request = ( typeof request != 'undefined' && request instanceof Array ) ? request : [];
var pendingAjax = ( typeof pendingAjax != 'undefined' && pendingAjax instanceof Array ) ? pendingAjax : [];

使用.ajaxStart 和.ajaxStop 跟踪活动请求。

var ajaxActive = 0;
$( document ).ajaxStart(function() 
  ajaxActive++;
  document.ajaxQueueFull = ajaxActive > 5;
);
$(document).ajaxStop(function() 
  ajaxActive--;
  document.ajaxQueueFull = ajaxActive > 5;

创建一个函数来构建新的请求

    function ajaxRequestNew(t, u, d, s) 

        var instance = request.length + 1;
        request[instance] = $.ajax(
            method: t,
            url: u,
            data: ajaxPost: d ,
            success: s
        );
        return instance;
    

现在创建您的请求以获取返回的实例编号

    var instance = ajaxRequestNew('POST', 
                                  'js/ajax_timezone.php', 
                                   ajaxAction : "ajaxGetTimezone", 
                                    tzoffset : "0", 
                                    tztimezone: "America/New_York" ,
                                    function(data)   
    );

$.ajax() 函数返回一个 XMLHttpRequest 对象。因此,我们使用 while 循环来检查我们的 ajax 何时真正被发送,并在请求停止时中止其他活动请求。

    while(request[instance] === null || (request[instance].readyState < 1 || request[instance].readyState > 4)) 
        if (document.ajaxQueueFull) 
            //abort existing requests
            $.each(request, function(i,v) 
                if (i !== instance) 
                    request[i].abort();
                
            );
        
    

将您的请求推入堆栈

    pendingAjax.push(request[instance]);

为您的请求创建回调

  var timezoneFailCallback = function(data) 
        console.log('fail');
        console.dir(data);
    ;

    var timezoneSuccessCallback = function(data) 
        console.log('success');
        console.dir(data);
    ;

使用何时应用回调

    $.when.apply($, pendingAjax).done( timezoneSuccessCallback ).fail( timezoneFailCallback);

代码可能需要对您的应用进行一些调整,但希望您能理解。如果您有任何问题,请告诉我。

【讨论】:

如果特定端点上的请求停止,这将解决问题,但如果所有请求都停止,而不管端点如何?在我的情况下,Chrome 在进入此状态时仅每秒启动一次请求(也许 Chrome 正在限制请求,因为应用程序一次发送太多,有点限制 Chrome 认为是行为不良的应用程序)? 【参考方案2】:

我偶然发现了完全相同的问题。一旦我禁用:

使用预测服务更快地加载页面

转到 高级设置 -> 隐私 -> ca。第三个复选框,一切都开始正常工作。我无法重现该错误。

jquery/ajax 轮询器在 Firefox 中完美运行。它只是 Chrome - 在 Linux 和 Windows 上测试。

这不是一个完美的解决方案,因为它不会影响全球范围内的用户 - 但也许你和我的情况相同 - 受众有限。

【讨论】:

这似乎也解决了我的问题。 这对我的情况没有任何影响,但有趣的假设。简单地说,Chrome 将每个选项卡/会话的未完成请求数限制为 6 个,因此可能在后台发生的其他事情没有显示在 Chrome 的开发工具中的网络监视器中。【参考方案3】:

我知道这是一个旧线程,但我将其发布给那些争先恐后地为此寻找某种答案的人。 我也不得不处理这个令人头疼的问题。我的问题是由于广告拦截器阻止了其中包含“优惠券”一词的 API 调用。它在保持请求状态的同时阻止了请求。在几个块之后,每个请求都会自动进入挂起状态,因为有太多(我认为大约 6 或 7 个)实时请求。

在您的 chrome 地址栏中键入 chrome://net-internals/#events 以检查请求。这将使您更清楚地了解问题。 我附上了两张我在试图弄清楚这一点时拍摄的图像。

debugger screenshot

net-internal screenshot

【讨论】:

【参考方案4】:

如果您控制服务器端,这可能适用于您的情况: 添加到服务器的响应 headers[ 'Connection' ] = 'close' 就我而言,“保持活力”是问题的原因

【讨论】:

【参考方案5】:

经过三天的头疼,我意识到我在 mysql 事务中调用了一个数据库备份函数。

【讨论】:

以上是关于Chrome 中 JQuery 停止和挂起的 ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章

进程的阻塞和挂起的区别

进程的阻塞和挂起的区别

当应用程序被终止时并在后台使用 FusedLocationProviderClient 和挂起的 Intent 但在不规则时间获取位置

如何编写 ADPlus 脚本以方便客户用于诊断崩溃和挂起

虚拟机下安装的Linux系统怎么挂起?? 怎么关闭系统才不会对系统有影响?

使用 apollo 客户端钩子停止挂起的请求