【问题标题】:Why does $.getJSON() block the browser?为什么 $.getJSON() 会阻止浏览器?
【发布时间】:2011-05-20 13:58:48
【问题描述】:

我有一个页面,其中列出了我们为客户监控的硬件设备。显示的每一行还显示设备的状态,即它是否正在运行、暂停、启动等。

为了缩短页面加载时间,我列出了设备,但在页面呈现之前不查询它们的状态。这是因为某些查询(例如通过 SNMP 或其他 API)可能需要 5-10 秒才能响应。因此,对于一个包含十个设备的列表,用户查看空白页面可能需要一分钟多的时间。所以我改为执行以下操作 -

在设备列表页面我有以下脚本:

$(document).ready(function () {

  var devices = $('div[name="runStatus"]');
  devices.each(function () {

    // Get device ID (I embed this using the HTML5 data-* attributes/annotations)
    var deviceId = $(this).attr("data-deviceid");
    var url = "/devmanager/status/" + deviceId;

    $.getJSON(url, function (response) {
      // Not actually important to the question...set text status, colours etc
      $('div[data-deviceid="' + deviceId + '"]').text(response);
      //...
    });
  });
});

我发现如果我允许此脚本运行,页面上的所有链接都会变得无响应。

我猜这是因为我有很多几乎并行的异步请求被阻塞,直到它们从服务器得到响应并且不知何故“UI线程”被阻塞了?

但是我认为这不应该发生在 AJAX 中。

我发现这种“阻止”行为发生在 IE8、Chrome 8.0 和 Firefox 3.6 中。 Chrome 实际上会显示箭头光标 + 旋转厕所碗(我使用的是 Windows 7),就好像页面没有完全呈现一样。

我该如何解决这个问题?

【问题讨论】:

  • 设备集合中有多少项?您可能一次只能执行 2 或 3 个并发 Ajax 请求,其余的将排队,可能会减慢页面其余部分的加载速度(下载图像等)。
  • $('div[data-deviceid="' + deviceId + '"]').text(response);看起来像一个相当昂贵的选择器。至少在更大的页面上。如果您删除回调中的所有代码,然后页面运行得很快,这就是原因。值得一试!
  • @douglas, @mikael - 列表中有 6 项。设置这些值(在 for 循环中)发生在眨眼之间。
  • 如果您说该列表包含 50 多个项目,我不会对这种行为感到惊讶......但是 6.. 令人惊讶的是,六个同时异步请求足以堵塞浏览器/操作系统.您可以发布指向相关页面的链接吗?我想看看它在 Safari/Mac 上的表现如何,并通过可信赖的旧网络代理查看一下。
  • @Lee - 我会打开一个你可以测试的网站。制作内容在受密码保护的门户后面运行,因此您无法轻松访问。

标签: javascript ajax jquery


【解决方案1】:

事实证明这不是客户端的问题:

Would multiple calls to the same ASP.NET MVC action cause the browser to block?

Would multiple calls to the same ASP.NET MVC action cause the browser to block? - Answer

这是由 ASP.NET 的“设计使然”特性引起的,在该特性中,同一会话中发出的多个请求会被序列化。

【讨论】:

    【解决方案2】:

    我想您在处理多个请求时遇到了浏览器限制。

    您是否尝试过使用 Fiddler 并查看时间线以查看阻塞的内容?

    这个 SO 问题可能会有所帮助:

    How many concurrent AJAX (XmlHttpRequest) requests are allowed in popular browsers?

    【讨论】:

      【解决方案3】:

      我从来没有遇到过 $.getJSON() 的问题。据我所知,它是异步的。 可能发生的是 javascript 错误,因为您正在尝试这样做:

      $('div[data-deviceid="' + deviceId + '"]').text(response);
      

      我猜这里有一个错误,因为 response 是一个 javascript 对象或数组,而不是字符串。 你应该做的是 text(response.desiredProperty)text(response[index]) 根据对象的类型 response 是。

      由于 javascript 错误有时会使我们的浏览器出现意外行为,这可能(仅可能)是您的问题。

      【讨论】:

      • 这不是 javascript 错误。响应也是一个字符串..相信我。我在 Firebug/Chrome 开发工具中检查了所有这些。问题肯定与异步调用有关。没错,$.getJSON 是调用 $.ajax() 的异步速记方法。
      • 另外...当我用$('div[data-deviceid="' + deviceId + '"]').text(response); 注释掉这一行时,问题仍然存在。
      • 有趣...我只是认为这可能是问题,但事实证明我完全错了。这个问题将我们引向 ScottE 的答案,这非常有趣,并且可能发生在很多不同的情况下。我会再次检查这个,看看你做了什么来解决/解决这个问题。
      【解决方案4】:

      听起来 getJSON 正在使用 asynchronous: false 作为 xhr 的选项。 jquery 会使用它作为默认值,这让我有点吃惊,因为出于您所描述的原因,这几乎总是一个坏主意。

      目前没有时间进行更多研究,但这是我要采取的第一条路径。

      【讨论】:

      • 根据文档,$.getJSON() 是一个简写的 $.ajax() 调用,它设置为 async:true。
      猜你喜欢
      • 1970-01-01
      • 2015-12-17
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 2021-09-19
      • 2021-10-18
      相关资源
      最近更新 更多