在Chrome浏览器中,JQuery的Ajax请求被卡住或挂起

25

我的应用程序中,偶尔会出现通过JQuery 1.8发出的Ajax调用长时间处于“挂起”状态(有时长达17分钟)。

我已经搜索了这个问题并尝试了所有可能的解决方案:

  1. 我没有安装广告拦截器。
  2. 我在Chrome浏览器中禁用了“预测网络操作以提高页面加载性能”的标志。
  3. 我还添加了查询字符串来使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"

查看图片:https://drive.google.com/file/d/0B9uQiZLJG1csNzlPcHZEWHl1Z2c/view


你有轮询周期吗?我也遇到了这个问题,因为有太多的请求(每1.5秒50个请求),所以 Chrome 等待所有请求完成,然后(26秒后)才处理最新的请求,即使它只需要 0.1 秒。 - Ivan Ivanov
我有一个每5分钟轮询一次的周期。然而,我们不明白它如何证明Chrome停顿了17分钟。减少轮询间隔是否解决了你的问题? - Wasafa1
根据<a href="https://developer.chrome.com/devtools/docs/network#resource-network-timing">Chrome的解释</a>,停滞时间是请求在发送之前等待的时间。这个时间包括代理协商所花费的任何时间。此外,当浏览器等待已经建立的连接可供重用时,这段时间也将被计入,遵守Chrome的“每个源最多六个TCP连接”的规则。 - Sablefoste
当我发出请求时,我一直收到相同的待处理消息。在我的情况下,我接收到的数据存在问题。我选择了一个新的匿名类型(使用C#和LINQ),而不是整个模型并发送它,这样就解决了问题。虽然我不知道为什么。 - Hamid Mosalla
如果您的某个服务未能完成请求并发送响应,最终您将面临所有ajax请求挂起的情况。请查看第一个给您提供挂起状态的服务。 - Skvettn
6个回答

8
我遇到了完全相同的问题。当我禁用以下选项时:

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

高级设置 -> 隐私 -> 第3个复选框 ,一切都开始正常工作。我无法再现错误。
在 Firefox 中,jquery/ajax 轮询器可以完美运行。只有在 Linux 和 Windows 上测试的 Chrome 出现问题。
这不是一个完美的解决方案,因为它不会在全局意义上影响用户,但也许你和我的情况一样——受众有限。

这似乎也解决了我的问题。 - kristinalim
这在我的情况下没有任何影响,但是这是一个有趣的假设。简单来说,Chrome限制每个选项卡/会话的未完成请求数量为6,因此可能还有其他在Chrome开发工具中的网络监视器中没有显示出来的后台操作。 - kashiraja

4
你可以尝试这个。 现在使用实际可工作的代码进行更新 (使用了自己的一些时区代码,因此请原谅对时区的引用) 首先初始化数组并运行请求计数逻辑
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);

代码可能需要稍作调整以适应您的应用程序,但希望您可以理解。如果有任何问题,请告诉我。

1
如果一个特定端点的请求停滞不前,这将解决问题,但是如果所有请求都停滞不前,无论端点如何呢?在我的情况下,当Chrome进入此状态时,每秒钟只会启动一次请求(也许Chrome正在限制请求,因为应用程序一次发送太多请求,以限制Chrome认为是行为不良的应用程序)? - kashiraja

3
我知道这是一个旧帖子,但我发布这篇文章是为了那些正在拼命寻找答案的人们。 我也遇到了这个难题。我的问题是由于广告拦截器阻止了一个API调用中含有“coupon”单词的请求。它会在保持请求活动的同时阻止请求。由于有太多(我认为大约有6或7个)活动请求,所以经过几次阻止后,每个请求都会自动进入挂起状态。
在chrome地址栏中键入chrome://net-internals/#events以检查请求。这将为您提供更清晰的问题概述。 我附上了两张图片,当我试图解决这个问题时捕获的。 调试器截图 内部网络截图

2
如果您控制服务器端,这可能适用于您的情况: 将headers[ 'Connection' ] = 'close'添加到服务器响应中。 在我的情况下,“keep-alive”是问题的原因。

0

可以尝试使用setTimeout。

试试使用这个

function ReadServer() {
    handleTimeInfo = setTimeout(function run() {
        /*You function pennding server*/
        TimerInfo();
    }, 60*1000);
    

function TimerInfo(){
    handleTimeInfo = setTimeout(function run() {ReadServer();}, 60*1000);           
}

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接