传说中的comet(iframe版)?

comet有两种实现方式:长轮询(long-polling)和iframe流(streaming)。

demo下载:comet-iframe.zip

comet相关资料:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

之前一篇随笔已经写了长轮询的代码,虽然不知道那是不是就是正确的,因为我感觉就像是普通的ajax,这里写的就是iframe流的方式。

前端代码:

View Code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Comet demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
var comet = {
connection :
false,
iframediv :
false,
timer :
0,
initialize:
function() {
if (!-[1,]) {
// For IE browsers
comet.connection = new ActiveXObject("htmlfile");
comet.connection.open();
comet.connection.write(
"<html>");
comet.connection.write(
"<script>document.domain = '"+document.domain+"'");
comet.connection.write(
"</html>");
comet.connection.close();
comet.iframediv
= comet.connection.createElement("div");
comet.connection.appendChild(comet.iframediv);
comet.connection.parentWindow.comet
= comet;
comet.iframediv.innerHTML
= "<iframe id='comet_iframe' name='comet_iframe' src='./backend.php'></iframe>";
var comet_iframe = comet.connection.getElementById("comet_iframe");
comet.timer
= window.setInterval(function(){
if(comet_iframe.readyState === "complete"){
comet_iframe.src
= comet_iframe.src;
}
},
1000*65)
}
else{
comet.connection
= document.createElement('iframe');
comet.connection.onload
= function(){
comet.connection.src
= comet.connection.src;
}
comet.connection.setAttribute(
'id','comet_iframe');
comet.connection.setAttribute(
'src','./backend.php');
comet.connection.style.display
= "none";
document.body.appendChild(comet.connection);
}
},
// this function will be called from backend.php
printServerTime: function (time) {
document.getElementById(
'content').innerHTML = time;
},
onUnload:
function() {
if (comet.connection) {
comet.connection
= false; // release the iframe to prevent problems with IE when reloading the page
}
}
}
window.onload
= function(){
comet.initialize();
}
window.onbeforeunload
= function(){
comet.onUnload();
}
</script>
</head>
<body>
<div id="content">The server time will be shown here</div>
</body>
</html>

后台代码:

View Code
<?php

header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
flush();

?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Comet php backend</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>

<script type="text/javascript">
// KHTML browser don't share javascripts between iframes
var is_khtml = navigator.appName.match("Konqueror") || navigator.appVersion.match("KHTML");
if (is_khtml)
{
var prototypejs = document.createElement('script');
prototypejs.setAttribute(
'type','text/javascript');
prototypejs.setAttribute(
'src','prototype.js');
var head = document.getElementsByTagName('head');
head[
0].appendChild(prototypejs);
}
// load the comet object
var comet = window.parent.comet;
</script>

<?php

while(1) {
echo '<script type="text/javascript">';
echo 'comet.printServerTime('.time().');';
echo '</script>';
flush(); // used to send the echoed data to the client
sleep(1); // a little break to unload the server CPU
}

?>
</body>
</html>

就像资料里所说的,“在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据”,通过iframe里的内容进行长时间的请求,当需要传输内容时通过调用父页面js方法来实现页面展示,以此达到comet所需要的效果。

使用iframe流的一个不足就是在IE、opera、chrome浏览器下,始终会显示下载没完成,并且鼠标及浏览器上的那个圈一直在转动,在IE678下,google的大牛们通过使用“htmlfile”解决了这个问题,IE9我试了,并不支持"htmlfile",当然IE9那个圈已经不转了。但是opera、chrome不支持“htmlfile”,无法解决。

iframe的另一个问题就是请求的超时,我们需要判断当iframe超时时,对其刷新重新建立连接。在普通情况下,我们可以通过iframe的onload事件进行刷新,当iframe连接内容超时时就会触发onload事件。在“htmlfile”下iframe却不支持onload,但是能读取到iframe的readyState,当readyState为complete时即表示请求超时,所以我们可以通过setInterval来判断iframe的readyState进行刷新。

至于php代码,本人不懂,无法做出解答。

posted on 2011-07-20 14:12  Lecaf  阅读(3515)  评论(1编辑  收藏  举报