它比我最初想的更简单。基本上你有一个页面,什么都不做,直到你想要发送的数据可用(例如,一个新的消息到达)。
这里是一个非常基本的例子,它会在2-10秒后发送一个简单的字符串。 1在3次机会返回错误404(以显示错误处理在即将到来的Javascript示例中)
msgsrv.php
if(rand(1,3) == 1){
/* Fake an error */
header("HTTP/1.0 404 Not Found");
die();
}
/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>
注意:对于一个真正的网站,在像Apache这样的普通网络服务器上运行这个网站将很快占用所有的“工作线程”,并使它无法响应其他请求。有几种方法,但是建议写一个“long-poll服务器”在类似Python的twisted,它不依赖于每个请求一个线程。 cometD是一个流行的(有多种语言),Tornado是一个专门为这样的任务(它是为FriendFeed的长轮询代码构建的)一个新的框架…但作为一个简单的例子,Apache是足够的!这个脚本可以很容易地以任何语言编写(我选择Apache / PHP,因为它们是非常常见的,我碰巧在本地运行它们)
然后,在Javascript中,请求上述文件(msg_srv.php),并等待响应。当你得到一个,你行动的数据。然后请求文件并再次等待,处理数据(并重复)
以下是这样的页面的示例。当页面加载时,它发送对msgsrv.php文件的初始请求。如果成功,我们将消息附加到#messages div,然后1秒钟后我们调用再次调用waitForMsg函数,触发等待。
1秒setTimeout()是一个真正的基本速率限制器,它工作正常没有这个,但如果msgsrv.php总是立即返回(例如语法错误) – 你洪水的浏览器,它可以迅速冻结。这将更好地检查该文件是否包含有效的JSON响应,和/或保持运行的请求每分钟/秒,并适当地暂停。
如果页面错误,它将错误附加到#messages div,等待15秒,然后再次尝试(与每个消息后等待1秒的方式相同)
这种方法的好处是它是非常有弹性。如果客户端互联网连接死亡,它将超时,然后尝试并重新连接 – 这是轮询工作长度固有的,不需要复杂的错误处理
无论如何,long_poller.htm代码,使用jQuery框架:
BargePollerbody{ background:#000;color:#fff;font-size:.9em; }
.msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
.old{ background-color:#246499;}
.new{ background-color:#3B9957;}
.error{ background-color:#992E36;}
function addmsg(type, msg){
/* Simple helper to add a div.
type is the name of a CSS class (old/new/error).
msg is the contents of the div */
$("#messages").append(
"
);
}
function waitForMsg(){
/* This requests the url "msgsrv.php"
When it complete (or errors)*/
$.ajax({
type: "GET",
url: "msgsrv.php",
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:50000, /* Timeout in ms */
success: function(data){ /* called when request to barge.php completes */
addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
setTimeout(
waitForMsg, /* Request next message */
1000 /* ..after 1 seconds */
);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
addmsg("error", textStatus + " (" + errorThrown + ")");
setTimeout(
waitForMsg, /* Try again after.. */
15000); /* milliseconds (15seconds) */
}
});
};
$(document).ready(function(){
waitForMsg(); /* Start the inital request */
});
BargePoll message requester!