Chrome无法处理jquery ajax查询

我在jquery中有以下查询。 它正在读取使用Nginx的长轮询模块设置的Nginx订阅/发布对的“发布”地址。

function requestNextBroadcast() { // never stops - every reply triggers next. // and silent errors restart via long timeout. getxhr = $.ajax({ url: "/activity", // dataType: 'json', data: "id="+channel, timeout: 46000, // must be longer than max heartbeat to only trigger after silent error. error: function(jqXHR, textStatus, errorThrown) { alert("Background failed "+textStatus); // should never happen getxhr.abort(); requestNextBroadcast(); // try again }, success: function(reply, textStatus, jqXHR) { handleRequest(reply); // this is the normal result. requestNextBroadcast(); } }); } 

该代码是聊天室的一部分。 发送的每条消息都以null rply(200 / OK)回复回复,但数据已发布。 这是在数据返回时读取订阅地址的代码。

使用超时,聊天室中的所有人都会每隔30到40秒发送一条简单的消息,即使他们没有输入任何内容,因此这段代码需要读取大量数据 – 每40秒至少有2条消息可能更多。

该代码在EI和Firefox中100%坚如磐石。 但在Chrome中,大约5个读取失败了。

当Chrome失败时,它会超时46秒。

该日志一次显示一个/活动网络请求未完成。

我已经在这个代码上爬了3天了,尝试各种想法。 每当IE和Firefox工作正常而Chrome失败时。

我所看到的一个建议是使呼叫同步 – 但这显然是不可能的,因为它会长时间锁定用户界面。

编辑 – 我有一个部分解决方案:代码现在是这个

 function requestNextBroadcast() { // never stops - every reply triggers next. // and silent errors restart via long timeout. getxhr = jQuery.ajax({ url: "/activity", // dataType: 'json', data: "id="+channel, timeout: , error: function(jqXHR, textStatus, errorThrown) { window.status="GET error "+textStatus; setTimeout(requestNextBroadcast,20); // try again }, success: function(reply, textStatus, jqXHR) { handleRequest(reply); // this is the normal result. setTimeout(requestNextBroadcast,20); } }); } 

结果有时会延迟回复,直到$ delay(15000)发生,然后排队的消息太快到达了。 我一直无法通过这种新安排来删除消息(仅通过netwrok optomisation测试)。

我非常怀疑网络问题的延迟是什么 – 所有机器都是我真正的机器中的虚拟机,并且本地局域网中没有其他用户。

编辑2(BST周五凌晨2:30) – 更改代码以使用promises – 并且操作的POST开始显示相同的症状,但接收方开始正常工作! (???? !!! ???)。 这是POST例程 – 它正在处理一系列请求,以确保一次只有一个请求未完成。

 function issuePostNow() { // reset heartbeat to dropout to send setTyping(false) in 30 to 40 seconds. clearTimeout(dropoutat); dropoutat = setTimeout(function() {sendTyping(false);}, 30000 + 10000*Math.random()); // and do send var url = "handlechat.php?"; if (postQueue.length > 0) { postData = postQueue[0]; var postxhr = jQuery.ajax({ type: 'POST', url: url, data: postData, timeout: 5000 }) postxhr.done(function(txt){ postQueue.shift(); // remove this task if ((txt != null) && (txt.length > 0)) { alert("Error: unexpected post reply of: "+txt) } issuePostNow(); }); postxhr.fail(function(){ alert(window.status="POST error "+postxhr.statusText); issuePostNow(); }); } } 

关于8中的一个动作,对handlechat.php的调用将超时,并出现警报。 警报一旦确定,所有排队的消息都会到达。

我还注意到,在写出其他人会看到的消息之前,手机呼叫已经停止。 我想知道是否可能是一些奇怪的处理会话数据的PHP。 我知道它仔细排队呼叫,以便会话数据不被破坏,所以我一直小心使用不同的浏览器或不同的机器。 只有2个php工作线程,但是php不用于处理/活动或静态内容的服务。

我也认为它可能是nginx工作者或php处理器的短缺,所以我提出了这些。 现在更难以让事情失败 – 但仍然可能。 我的猜测是/ activity调用现在在30次中失败,并且根本不会丢弃消息。

谢谢你们的意见。


调查结果摘要。

1)Chrome中的一个错误已经在代码中存在了一段时间。
2)幸运的是,可以使bug显示为未发送的POST,并且当它超时时,Chrome将处于这样一种状态,即重复POST将成功。
3)用于存储$ .ajax()的返回的变量可以是本地的或全局的。 新的(promises)和旧的格式调用都会触发bug。
4)我没有找到工作或避免错误的方法。

伊恩

我与Chrome有一个非常相似的问题。 我正在进行Ajax调用,以便每秒从服务器获取时间。 显然,Ajax调用必须是异步的,因为如果没有,它会在超时时冻结接口。 但是,一旦Ajax调用之一失败,每个后续调用都是如此。 我首先尝试将超时设置为100毫秒,并且在IE和FF中运行良好,但在Chrome中则不行。 我最好的解决方案是将类型设置为POST,并为我解决了chrome的错误:

  setInterval(function(){ $.ajax({ url: 'getTime.php', type: 'POST', async: true, timeout: 100, success: function() { console.log("success"); }, error: function() { console.log("error"); } }); }, 1000); 

更新:我认为这里的实际根本问题是Chrome的缓存方式。 似乎当一个请求失败时,该缓存会被缓存,因此后续请求永远不会发生,因为Chrome会在启动后续请求之前获得缓存失败。 如果您转到Chrome的开发人员工具并转到“网络”标签并检查每个请求,就可以看到这一点。 在失败之前,每秒都会对getTime.php发出ajax请求,但是在1次失败之后,永远不会启动后续请求。 因此,以下解决方案对我有用:

  setInterval(function(){ $.ajax({ url: 'getTime.php', cache: false, async: true, timeout: 100, success: function() { console.log("success"); }, error: function() { console.log("error"); } }); }, 1000); 

这里的变化是,我禁止缓存到这个Ajax查询,但为了这样做,类型选项必须是GET或HEAD,这就是我删除’ type: 'POST' ‘的原因(GET是默认的)。

尝试将您的轮询function移动到网络工作者,以防止铬合金冻结。 否则你可以尝试使用jquery对象的ajax .done()。 一个人总是在我的铬合金。

我觉得getxhr应该以“var”为前缀。 您是不是每次都想要一个完全独立的新请求而不是在成功/失败处理过程中覆盖旧请求? 可以解释为什么添加setTimeout时行为会“改善”。 我也可能遗漏了一些东西;)

评论不会格式化代码,因此重新发布为第二个答案:

我认为Michael Dibbets正在使用$ .ajax.done – 延迟模式将处理推送到事件循环的下一轮,我认为这是需要的行为。 请参阅: http : //www.bitstorm.org/weblog/2012-1/Deferred_and_promise_in_jQuery.html或http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/

我会尝试类似的东西:

 function requestNextBroadcast() { // never stops - every reply triggers next. // and silent errors restart via long timeout. getxhr = jQuery.ajax({ url: "/activity", // dataType: 'json', data: "id="+channel, timeout:  }); getxhr.done(function(reply){ handleRequest(reply); }); getxhr.fail(function(e){ window.status="GET error " + e; }); getxhr.always(function(){ requestNextBroadcast(); }); 

注意:我很难找到Promise.done和Promise.fail的回调参数的文档:(

也许它可以通过更改推模块设置(有一些)来解决 – 你能发布这些吗?

从我的头顶:

  • 将它设置为区间轮询,有点可以解决它
  • 并发设置可能会产生一些影响
  • 消息存储可能用于避免丢失数据

我还会使用像查尔斯这样的东西来看看网络/应用程序层究竟发生了什么