从long polling 到 websockets

在实时显示数据的web程序中,需要不断将服务端数据送到客户端显示,在客户端获取数据的方式上,web程序的实现方法经历了从“不断请求“到“long polling“再到websockets的历程。

long polling

最初的做法是,客户端浏览器使用 setInterval 或者 setTimeout 来不断Ajax请求后端。

setInterval(function () {
    $.ajax({url: "server"}).then(function (data) {
            // show some thing with data
    }   
}, 3000)

使用setInterval有个缺陷,如果在setInterval指定的时间内比如上面的3秒内,服务端没有返回,那么其对应的那次请求就丢了数据。还有一个缺陷是,不同的ajax返回顺序不一定按照请求顺序返回。

可以使用递归setTimeout来解决上面两个问题。

(function poll() {
    setTimeout(function () {
    // ajax
        $.ajax({url: 'server'}).then(function(data) { // show data poll() // 递归 })
    }, 3000)
})()

这种不断请求的方法肯定是很耗带宽的。可以考虑使用long polling来优化。long polling没有做什么魔法的事情,就是服务端做了一点点的改变。这一点点改变就是“由原来的立即返回,改为延时返回“。也就是说,请客户端请求过来后,服务端原本不管有没有数据,都会返回该请求的,现在变为“等到有数据后“返回。这就意味着客户端的一次请求肯定是有数据的,从而充分利用了每一次客户端的请求。

var http = require("http");
var requests = [];

http.createServer(function(request, response) {
    // 先把请求放进数组里暂存起来
    requests.push({
        response: response,
        timestamp: new Date().getTime()
    });
}).listen(8000);

setInterval(function() {
    var expiration = new Date().getTime() - 5000;
    var data = getData();
    for (var i = requests.length - 1; i >= 0; i--) {
        var response = requests[i].response;
        if (requests[i].timestamp < expiration) { // 请求超过5秒的直接返回空
            response.writeHead(200, { "Content-Type": "text/plain" });
            response.end("");
        } else { 
            if (data) { // 如果有数据则返回之,如果没有则等待下一个interval
                response.writeHead(200, { "Content-Type": "text/plain" });
                response.end(data);
            }
        }
    }
}, 1000);

websockets

关于websockets,维基百科给了很棒的介绍
利用websockets,服务端可以主动推送数据到客户端。

使用起来也是无比简单。客户端,

var myWebSocket = new WebSocket("ws://www.websockets.org");
myWebSocket.onopen = function(evt) { alert("Connection open ..."); };
myWebSocket.onmessage = function(evt) { alert( "Received Message: " + evt.data); };
myWebSocket.onclose = function(evt) { alert("Connection closed."); }; 
myWebSocket.send("Hello WebSockets!");
myWebSocket.close();

服务端

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: %s', message);
  });

  ws.send('something');
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值