我的网络应用使用“长轮询”方法来跟踪我服务器的最新数据。服务器只有在有新数据时才会响应,这可能相隔很多分钟。 (这是一个加热控制系统,您只能在室温变化或有人更改设置时看到更新。)
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的Android手机上,在手机进入睡眠状态超过10分钟后会发生奇怪的事情。邮件请求似乎被删除,我认为这是合理的,因为手机是睡着了。在Chrome调试器的“网络”标签中,POST请求的状态文本显示(已取消)。
问题是当我取消请求时唤醒手机,调用success()或error()函数,我的网络应用程序永远不会更新。 $ .ajax()违背承诺给我回电话。
问题只发生在某些设备上。我已经能够通过借用朋友的设备进行一些临时测试。到目前为止,我只看到Android手机上的问题。但不是手机连接到充电器。我没有在苹果设备或Windows PC上看到它。
我尝试在ajax设置中添加超时:
timeout: 120 * 1000,
这有帮助,因为error()函数最终在唤醒后最多调用2分钟。但我希望用户在1或2秒内看到更新。我不想让超时这么短,因为它会造成不必要的服务器流量。
我也试过通过在Can any desktop browsers detect when the computer resumes from sleep?中描述的一秒钟setInterval中寻找迟到来检测设备是否处于睡眠状态。 当我检测到唤醒时,我中止()帖子并启动另一个。这在大多数情况下都有帮助但事实证明这是不可靠的。有时时间事件似乎在睡眠期间保持正常滴答,并且无论如何都会取消发布请求。它并不像是一个可靠的解决方案。
我使用的是最新版本的jQuery:(2.1.2)和Chrome(47)。
答案 0 :(得分:0)
我不确定这是否有效,我现在无法测试但是试一试
$(window).focus(function() {
updater();
});
答案 1 :(得分:0)
过去我遇到过问题,当手机进入睡眠状态时,JavaScript调用会被暂停。我最终得到的解决方案是使用似乎暂停的window.setInterval()
,但是当电话被唤醒时恢复生机。
所以我建议设置一个间隔,每隔一段时间取消一次呼叫并重新启动它。这可能有助于它通过手机睡眠生存。
大致类似于:
var myCall = $.ajax({...});
Window.setInterval (refreshCall(), 10000);
function refreshCall (){
myCall.abort ();
myCall = $.ajax({...});
}
答案 2 :(得分:0)
这样的高级观察者功能怎么样:
var restartTimer = null;
function updater(){
$.ajax({
type: "POST",
url: "/listen",
data: version,
success: function (data) {
version = handleUpdates(data);
clearTimeout(restartTimer);
updater();
},
error: function () {
clearTimeout(restartTimer);
setTimeout(updater, 1000);
}
});
}
// Kick it when the phone wakes up.
$(window).focus(function(){
restartTimer = setTimeout(function(){
initializeAll();
}, 6000);
updater();
});
你知道$(窗口).focus会在手机唤醒时触发,所以你尝试更新器(),就像Almis建议的那样,但是有一个故障安全计时器。如果更新程序触发(在笔记本电脑或iOS上),计时器将被取消并且一切正常,但如果更新程序已用完,则故障安全计时器将在6秒内触发,并通过调用initializeAll()重新启动整个应用程序。
答案 3 :(得分:0)
setInterval
如何存储调用时间,然后将上次调用时间与当前时间进行比较 - 如果间隔为10秒,则自上次运行后经过的时间为5分钟,你可以假设你刚从睡梦中醒来?然后中止当前的ajax调用,然后重新启动它。
答案 4 :(得分:0)
最好的答案是“不要那样做”。您正在让服务器等待响应,同时跟踪服务器端的更改。让服务器响应并在一段时间内进行jQuery ping。如果你想在没有状态改变的情况下阻止实际刷新,你可以包括lastchanged或haschanged,但是如果服务器以任何方式执行相同的工作,只需让它响应并等待下一次轮询。
setInterval(function () {
$.post({"/listen", version, function (data) {
if(data.haschanged)
version = handleUpdates(data);
}).fail(function () {
// any error correction on failed call
});
}, 1000);