1、Ajax建立的Server Push
只能由后台向前台推送数据,如果前台想发送数据给后台则需要单独再发一个请求。
这里使用的例子就是一个在线CD销售页面,前台发起ajax请求,后台随机取一个数,从现在库中减去获得的随机数,然后返回给前台;
前台如果想改变库存的数据,在文字输入框输入相应的数量,然后提交给后台。
界面大致是这个样子
图中的“27”就是剩余的CD数量,上文提及的“库存”实际是使用一个txt文本进行保存的。
因为代码是从网上一篇文章(可点击查看详情)中下载过来的,他使用了prototype中的ajax,这里就没有作修改。需要下载源代码的,请点击这里>>
需要说明的,它的主页中form的默认提交行为没有被阻止掉,将会导致页面被刷新。可以使用οnsubmit=”return false;”进行阻止,AjaxLongPolling.js的初始化函数中对form的submit再进行监听就可以了。
目录结构大致是这样子:
页面载入完成后,向后台发送ajax请求,当ajax成功返回后将重复执行上一次操作(直到返回的数量为0,则中止上述循环)
function connectToServer() {
new Ajax.Updater({
success : 'CD Count',
failure : 'errors'
}, 'LongPolling.php', {
method : 'get',
onSuccess : function(transport) {
if (parseInt(transport.responseText)) {
connectToServer();
}
}
});
}
想要修改后台的“库存”数量,则需要另外一个ajax
function purchaseCD() {
new Ajax.Updater({
success : 'CD Count',
failure : 'errors'
}, 'LongPolling.php', {
method : 'get',
parameters : {
num : $('txtQty').getValue()
}
});
}
虽然是同一个提交地址LongPolling.php,但在LongPolling.php中是针对参数进行了处理的
<?php
$cd_stock = ("CdCount.txt");
function updateStock($num) {
global $cd_stock;
$count = file($cd_stock);
$count = (int)$count[0];
$count = $count - $num;
if ($count < 0) $count = 0;
$fp = fopen($cd_stock , "w");
fputs($fp , "$count");
fclose($fp);
echo $count;
}
function getCdCount()
{
srand();
$newOrder = rand(1, 3);
$sleeptime = rand(2, 10);
sleep(1);
updateStock($newOrder);
}
$num = $_GET['num'];
if ($num == "") {
getCdCount();
} else {
updateStock((int)$num);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>iframe commet</title>
</head>
<body οnlοad="Comet.initialize()">
<script type="text/javascript">
var Comet = {
connection : false,
_timer : 0,
initialize: function() {
if (window.ActiveXObject) {
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.connection.parentWindow.Comet = Comet;
var iframeEl = Comet.connection.createElement("iframe");
Comet.connection.body.appendChild(iframeEl);
//htmlfile中的iframe不支持对onreadystatechange的监听
Comet._timer = setInterval(function() {
if (iframeEl.readyState == "complete") {
iframeEl.src = iframeEl.src;
}
}, 10);
iframeEl.src = "test.php";
} else {
Comet.connection = document.createElement('iframe');
Comet.connection.onload = function(){
Comet.connection.src = Comet.connection.src;
}
Comet.connection.setAttribute('src','test.php');
Comet.connection.style.display = "none";
document.body.appendChild(Comet.connection);
}
},
onMessage: function (msg) {
document.getElementById('content').innerHTML = msg;
},
onUnload: function() {
if (Comet.connection) {
Comet.connection = false;
}
if (Comet._timer) {
clearInterval(Comet._timer);
Comet._timer = null;
}
}
}
window.onbeforeunload = function() {
Comet.onUnload();
}
</script>
<div id="content">后台返回数据</div>
</body>
</html>
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Thu, 01 Jan 1970 00:00:00 GMT");
?>
<!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">
var Comet = window.parent.Comet;
</script>
</body>
</html>
<?php
date_default_timezone_set("Asia/Shanghai");
while(1) {
echo str_pad(' ', 4096);
echo '<script type="text/javascript">';
echo 'Comet.onMessage("当前服务器时间:'.date("Y-m-d H:i:s").'");';
echo '</script>';
ob_flush();
flush();
sleep(1);
}
?>
参考链接:
1、Comet Programming:the Hidden IFrame Technique
2、Comet Programming:Using Ajax to Simulate Server Push
5、Browser与Server持续同步的做法介绍(Polling,Comet,Long Polling,WebSocket)
关于Node.js的Web Socket,之前写过一篇Demo《基于Node.js的Web Socket》