【发布时间】:2016-03-24 07:01:26
【问题描述】:
我的网络应用程序使用“长轮询”方法来及时了解来自我的服务器的最新数据。服务器仅在有新数据时才响应,这可能相隔数分钟。 (这是一个供暖控制系统,只有在室温变化或有人更改设置时才能看到更新)。
var version = "0";
function updater() {
$.ajax({
type: "POST",
url: "/listen",
data: version,
success: function (data) {
version = handleUpdates(data);
updater();
},
error: function () {
setTimeout(updater, 1000);
}
});
}
它在桌面浏览器和手机上都可以正常工作,但有一种情况除外。我发现在带有 Chrome 的安卓手机上,手机进入睡眠状态超过 10 分钟后会发生一些奇怪的事情。发布请求似乎已被删除,我认为这是合理的,因为手机处于睡眠状态。在 Chrome 调试器的网络选项卡中,POST 请求的状态文本显示为(已取消)。
问题是当我在请求被取消时唤醒手机时,既没有调用success() 也没有调用error() 函数,并且我的网络应用程序永远不会更新。 $.ajax() 违背了承诺给我回电话。
该问题仅发生在某些设备上。通过向朋友借用设备,我已经能够进行一些临时测试。到目前为止,我只在安卓手机上看到过这个问题。但不是手机连接到充电器。我没有在任何平板电脑、苹果设备或 Windows PC 上看到它。
我尝试在 ajax 设置中添加超时:
timeout: 120 * 1000,
这很有帮助,因为 error() 函数最终会在唤醒后 2 分钟内被调用。但我希望用户在 1 或 2 秒内看到更新。我不想让超时时间这么短,因为它会造成不必要的服务器流量。
我还尝试通过在Can any desktop browsers detect when the computer resumes from sleep? 中描述的一秒 setInterval 中查找延迟来检测设备是否处于睡眠状态。 当我检测到唤醒时,我 abort() 发布并开始另一个。这在大多数情况下都有帮助。但事实证明是不可靠的。有时时间事件似乎在睡眠期间保持正常滴答作响,并且发布请求无论如何都会被取消。而且它感觉不像是一个可靠的解决方案。
我正在使用最新版本的 jQuery:(2.1.2) 和 Chrome (47)。
【问题讨论】:
-
尝试全局存储当前的promise,然后当你进入这个失败状态时,检查promise的.state()。它包含什么?如果它包含“待定”以外的任何内容,您可以将它与@spozun 的解决方案结合使用,以便在睡眠期后重新启动,而不会不必要地取消请求。
标签: javascript jquery ajax google-chrome long-polling