我在 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();
}
});
}
该代码是聊天室的一部分。发送的每条消息都会以空 rply(带有 200/OK)回复进行回复,但会发布数据。这是在数据返回时读取订阅地址的代码。
使用超时,聊天室中的所有人每 30 到 40 秒发送一条简单的消息,即使他们没有输入任何内容,因此该代码有大量数据可供读取 - 每 40 秒至少有 2 条甚至更多消息.
该代码在 EI 和 Firefox 中是 100% 坚如磐石的。但是大约 5 次阅读中的一篇在 Chrome 中失败了。
当 Chrome 失败时,超时时间为 46 秒。
日志显示在任何时候有一个 /activity 网络请求未完成。
我已经在这段代码上爬了 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: <?php echo $delay; ?>,
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 的情况下进行测试)。
我非常怀疑延迟是由于网络问题 - 所有机器都是我一台真实机器中的虚拟机,并且我的本地 LAN 没有其他用户。
编辑 2(英国夏令时星期五 2:30) - 将代码更改为使用承诺 - 动作的 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 的调用将超时并出现警报。一旦警报被确定,所有排队的消息都会到达。
而且我还注意到,handlechat 呼叫在写入其他人会看到的消息之前就停止了。我想知道它是否可能是 php 对会话数据的一些奇怪处理。我知道它会小心地将调用排队,以免会话数据损坏,所以我一直小心使用不同的浏览器或不同的机器。只有 2 个 php 工作线程,但是 php 不用于处理 /activity 或提供静态内容。
我还认为这可能是 nginx 工作人员或 php 处理器的短缺,所以我提出了这些。现在让事情失败变得更加困难——但仍然有可能。我的猜测是 /activity 调用现在失败了 30 次,并且根本不会丢弃消息。
并感谢你们的意见。
调查结果摘要。
1) 这是 Chrome 中的一个错误,已经在代码中出现了一段时间。
2) 如果运气好,该错误可以显示为未发送的 POST,并且当它超时时,它会使 Chrome 处于重复 POST 将成功的状态。
3) 用于存储 $.ajax() 返回的变量可以是本地的或全局的。新的(promises)和旧的格式调用都触发了这个错误。
4)我还没有找到解决这个问题的方法或方法。
伊恩