我正在尝试制作一个非常简单的彗星测试页面。我有一个主客户端页面,div ID 为#TextHistory。此页面中的 JavaScript 应创建一个到 back-end.php 的开放连接,该连接使用 JavaScript 更新值并将其刷新回客户端页面。我真的不确定我这样做是否正确...我的基础是如何实现基本的“长轮询”?.
我在客户端页面 (Firefox) 上发现 back-end.php 似乎没有返回任何内容,并且在 10 秒后超时。如果我取出 back-end.php 中的 PHP 循环,它会不断返回“DefaultData”并直接附加到 TextHistory DIV。我觉得我很接近,但做错了事。抱歉,这里的格式很奇怪,看起来有些标头和 PHP 标签是不允许的。
客户端:
$(document).ready(function() {
waitForMsg(); /* Start the inital request */
});
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 */
$("#TextHistory").append(
"<div class='msg "+ type +"'>New MSG: "+ msg +"</div>"
);
}
function waitForMsg(){
/* This requests the url "msgsrv.php"
When it complete (or errors)*/
$.ajax({
type: "GET",
url: "backend.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) */
},
});
};
</script>
</head>
<body>
<div id="container">
<div id="main">
<h2>Text Scrolling Test</h2>
<div id="TextHistory">
<p>First default line of text</p>
<p>Second default line of text</p>
</div>
</div>
</div>
</body>
</html>
Backend.php 称为:
<---php start --->
session_start();
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 2012 05:00:00 GMT");
flush();
<---php end --->
然后默认 HTML doctype、head、meta、jQuery include,
然后在体内:
<div id="LastMsg">DefaultData</div>
<---PHP Start --->
$OutputMsg = "Initial";
while (true) {
$OutputMsg .= "Something.";
echo "
<script type=\"text/javascript\">
$('#LastMsg').html(\"<p>$OutputMsg</p>\");
</script>
";
flush(); // Ensure the Javascript tag is written out immediately
sleep(1);
}
<---PHP END --->
您应该考虑使用带有输出缓冲的flush()。 PHP 在内部做了一些奇怪的事情,所以通常需要同时使用两者。
ob_start();
同时(真){
如果($新内容){ echo '我的新内容'; ob_flush(); 冲洗(); }
睡觉(1); }
尽管如此,您的长轮询方法是不正确的。您不想让浏览器连接永远保持打开状态,直到有数据推送到客户端为止。收到数据后,关闭连接,然后重新打开它。它基本上与内存/连接管理有关。
我认为你一开始就不应该在 PHP 中进行长轮询,因为它不是适合这项工作的工具(参见 #1)。 PHP 没有线程模型(无共享架构)并且扩展性很差。
例如,您可以使用 pusherapp(小型应用程序免费)来实现此目的,它将更加高效、易于实现。