长轮询/comet php 后端未刷新正确的数据 - 新手问题
我正在尝试制作一个非常简单的彗星测试页面。我有一个主客户端页面,div ID 为#TextHistory。此页面中的 javascript 应创建一个到 backend.php 的开放连接,该连接使用 javascript 更新值并将其刷新回客户端页面。我真的不确定我这样做是否正确......我基于它 如何实现基本的“长轮询”?。
我发现在客户端页面(FireFox)上,backend.php 似乎没有返回任何内容,并且在 10 秒后超时。如果我取出 backend.php 中的 php 循环,它会不断返回“DefaultData”并直接附加到 TextHistory DIV。我觉得我很接近,但做错了事。抱歉,这里的格式很奇怪,看起来有些 header 和 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 --->
I'm trying to put together a really simple comet test page. I have a main client page with a div ID of #TextHistory. The javascript in this page should create a open connection to backend.php which uses javascript to update a value and flush it back out to the client page. I'm really not sure if i'm doing this right at all...i've based it on How do I implement basic "Long Polling"?.
What i'm finding is on the client page (FireFox) it looks like the backend.php isn't returning anything and times out after 10 seconds. If I take out the php loop in the backend.php it constanty returns "DefaultData" and appends straight away to the TextHistory DIV. I feel like i'm close but doing something wrong. Sorry for the strange formatting here, it looks like some header and php tags aren't allowed.
Client Side:
$(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 which is called:
<---php start --->
session_start();
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 2012 05:00:00 GMT");
flush();
<---php end --->
then default html doctype, head, meta, jquery include,
then in the body:
<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 --->
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该考虑使用带有输出缓冲的flush()。 PHP 在内部做了一些奇怪的事情,所以你通常需要同时使用两者。
ob_start();
while (true) {
if ($newcontent) {
echo '我的新内容';
ob_flush();
冲洗();
睡眠
(1);
尽管如此
,您的长轮询方法是不正确的。您不想让浏览器连接永远保持打开状态,直到有数据推送到客户端为止。收到数据后,关闭连接,然后重新打开它。它基本上与内存/连接管理有关。
You should consider using flush() with output buffering. PHP does some weird things internally, so you normally are required to use both.
ob_start();
while (true) {
if ($newcontent) {
echo 'my new content';
ob_flush();
flush();
}
sleep(1);
}
Although, your approach to long polling is incorrect. You don't want to keep the browser connection open forever, only until there is data to push to the client. Once the data is received, you close the connection, and re-open it. It basically has to do with memory/connection management.
我认为你不应该首先在 PHP 中进行长轮询, 因为它不是适合这项工作的工具(参见#1)。 PHP 没有线程模型(不共享架构)并且可以扩展很糟糕。
例如,您可以使用 pusherapp(小型应用程序免费)来实现此目的,它将更加高效、易于使用实施。
I don't think you should not be doing long-polling in PHP in the first place, because it is not the right tool for the job(See #1). PHP does not have a thread-model(Share-nothing Architecture) and would scale badly.
You could for example use pusherapp(free for small apps) for this and it is going to be way more efficient, easy to implement.