更新
随着我继续收到对此的支持,我认为记住这个答案已有 4 年历史是合理的。网络的发展速度非常快,所以请注意这个答案。
我最近遇到了同样的问题并研究了这个主题。
给出的解决方案称为长轮询,要正确使用它,您必须确保您的 AJAX 请求具有“大”超时,并且始终在当前结束(超时、错误或成功)之后发出此请求。
长轮询 - 客户端
在这里,为了保持代码简短,我将使用 jQuery:
function pollTask() {
$.ajax({
url: '/api/Polling',
async: true, // by default, it's async, but...
dataType: 'json', // or the dataType you are working with
timeout: 10000, // IMPORTANT! this is a 10 seconds timeout
cache: false
}).done(function (eventList) {
// Handle your data here
var data;
for (var eventName in eventList) {
data = eventList[eventName];
dispatcher.handle(eventName, data); // handle the `eventName` with `data`
}
}).always(pollTask);
}
重要的是要记住(来自jQuery 文档):
在 jQuery 1.4.x 及以下版本中,如果请求超时,XMLHttpRequest 对象将处于无效状态;访问任何对象成员都可能引发异常。仅在 Firefox 3.0+ 中,脚本和 JSONP 请求不能被超时取消;即使脚本在超时期限之后到达,它也会运行。
长轮询 - 服务器
它没有任何特定的语言,但它会是这样的:
function handleRequest () {
while (!anythingHappened() || hasTimedOut()) { sleep(2); }
return events();
}
在这里,hasTimedOut
将确保您的代码不会永远等待,并且anythingHappened
将检查是否发生了任何事件。这sleep
是为了在没有任何反应的情况下释放你的线程来做其他事情。events
将以 JSON 格式(或您喜欢的任何其他格式)返回事件字典(或您可能喜欢的任何其他数据结构)。
它确实可以解决问题,但是,如果您像我在研究时一样担心可扩展性和性能,您可能会考虑我找到的另一种解决方案。
解决方案
使用插座!
在客户端,为避免任何兼容性问题,请使用socket.io。它尝试直接使用套接字,并在套接字不可用时回退到其他解决方案。
在服务器端,使用 NodeJS 创建一个服务器(此处为示例)。客户端将订阅与服务器一起创建的这个频道(观察者)。每当必须发送通知时,它都会在此频道中发布,并且订阅者(客户端)会收到通知。
如果您不喜欢此解决方案,请尝试 APE(Ajax Push Engine)。
希望我有所帮助。