Comet是一种用于web的推送技术,能使服务器实时地将更新的信息传送到客户端,而无须客户端发出请求,当前有三种实现方式,轮询 长轮询和iframe流。
轮询
客户端和服务器之间一直进行连接,每隔一段时间就询问一次
特点: 这种方式连接数会很多,一个接受,一个发送。而且每次发送请求都会有Http的Header,会很耗流量,也会消耗CPU的利用率
<body>
<div id="clock"></div>
<script>
let clock = document.getElementById('clock');
setInterval(function(){
let xhr = new XMLHttpRequest;
xhr.open('GET', '/clock', true);
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
clock.innerHTML = xhr.responseText;
}
}
xhr.send();
}, 1000);
</script>
</body>
server.js
let express = require('express');
let app = express();
app.use(express.static(__dirname));
app.get('/clock', (req,res) => {
res.header('Access-Control-Allow-Origin', 'http://localhost:8000');
res.end(new Date().toLocaleTimeString());
});
app.listen(8000);
长轮询
在打开一条连接以后保持,等待服务器推送来数据再关闭的方式。
特点: 这种方式在某种程度上减小了网络带宽和CPU利用率等问题。但由于http数据包的头部数据量往往很大(通常有400多个字节),真正被服务器需要的数据却很少(有时只有10个字节左右),这样的数据包在网络上周期性的传输,难免对网络带宽是一种浪费
<div id="clock"></div>
<script>
(function poll() {
let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080', true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
document.querySelector('#clock').innerHTML = xhr.responseText;
poll();
}
}
xhr.send();
})();
</script>
iframe流
在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长链接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。
特点: 浏览器兼容好
<div id="clock"></div>
<iframe src="http://localhost:8000/clock" frameborder="0" />
<script>
function setTime(ts) {
document.querySelector("#clock").innerHTML = ts;
}
</script>
server.js
const express = require('express');
const app = express();
app.use(express.static(__dirname));
app.get('/clock', function (req, res) {
res.header('Content-type', 'text/html');
setInterval(function () {
res.write(`<script>
parent.setTime('${new Date().toLocalString()}'); // 如果在子窗口调用父窗口的方法,通过parent(为window对象)
</script>`); // 如果使用res.send()则返回数据给客户端同时关闭连接
}, 1000);
});
app.listen(8000);