之前偶然看到这个 于是就查了一下 发现网上的资料博客基本都是在扯淡。。。。
首先总结一下网上博客那些错误
- 两者的区别是在实现的逻辑上 特别是服务端的实现方式相关 与用iframe还是ajax实现并没有关系
- 长轮询和长连接并没什么关系 长连接是传输层的一种实现 长轮询是应用层的一种实现 一般来说 相同的功能 web的可以使用反向ajax 服务器直接向浏览器发送数据实现 但是既然用轮询 那就研究一下吧 自己弄懂了之后 写了一个例子出来 我前端用js 后端用nodejs 框架用的express 其他平台差不多 客户端和服务端各有两种实现方式
客户端(浏览器)
0. 使用 setInterval 无脑轮询请求
function pollingCallback (e) {
log(e)
};
//进行轮询,间隔时间为3s,
setInterval(post,3000,url_polling,data,pollingCallback);
1. 递归请求
使用递归请求在回调函数里面发起新的请求
function pollingCallback (e) {
log(e);
//请求完成后进行下一次请求
post(url_polling, data, pollingCallback);
};
//开始请求数据
post(url_polling, data, pollingCallback);
这个两个的优缺点大家也都看的出来 两个方法需要配合服务器以及开发需求选择合适的就可以了
2. iframe
很多查到的资料还有使用iframe来实现轮询的 完全可以模拟方法0和1 post也用form也可以实现 而且还有个很大的好处:请求可以中断 但是我还没见用这种方法的实现 本篇不会过多讲这中方式
可以用 iframe 的reload函数进行刷新 以下代码没有测试 估计运行不了
//模拟 方法0 一旦有请求延迟 后面的再次请求的时候 前面的请求会自动取消
iframe.onload = function(){
pollingCallback(iframe.contentDocument);
}
setInterval(fuction(){iframe.src=url_polling;},2000);
//模拟 方法1
iframe.onload = function(){
pollingCallback(iframe.contentDocument.documentElement.innerHTML);
iframe.src=url_polling;
}
iframe.src=url_polling;
服务端(nodejs)
说明:getRespTpl() 返回一个模板对象 , checkNewData(callback) 用来检查是否有新数据 并有一个回调作为参数
0. 普通实现:每次请求都去查询新数据 并返回结果
exports.polling = function (req, resp) {
var pollingCallback = function (newData) {
var data = getRespTpl(req);
if (newData) {
data['data'] = newData;
};
resp.send(JSON.stringify(data));
}
checkNewData(pollingCallback);
}
1.使用长轮询实现:每次请求数据时先hold住连接不着急返回数据 等有新的数据后再返回新数据
当然客户端在这里有个超时时间 为了避免被超时 服务器需要每隔一段时间返回数据 为了方便起见这个下面的例子不包含超时逻辑
exports.longpolling = function (req, resp) {
var longpollingCallback = function (newData) {
var data = getRespTpl(req);
if (newData) {
data['data'] = newData;
resp.send(JSON.stringify(data));
}else{
//每次检查完后隔一段时间后进行第二次查询
setTimeout(checkNewData,3000,longpollingCallback);
//当然也可以马上进行查询 但是这样服务器压力可能会增大
//checkNewData(longpollingCallback);
}
}
checkNewData(longpollingCallback);
}
好了 现在可以两两组合看看了 2 × 2 就是四种方式了
组合 0-0:普通轮询
大部分轮询都是这样的组合 简单 容易实现 但是大部分网络请求都是无效的 浪费网络资源 而且有一个请求出问题了不影响后面的请求 但是一个请求延迟了后面的请求仍然会发送 无法保证数据的顺序
组合 1-0:优化了的普通轮询
这个是组合0-0的优化方式 同样大部分请求是无效的 但是能保证数据的顺序和请求的顺序是一致的 一旦请求出问题还可以重新获取这个请求 这个请求如果是
组合0-1:
这种组合你特么不是在逗我吗? 完全没有意义
组合 1-1 : 这就是长轮询!!!(尼玛终于讲到重点了)
这种方式很好的解决了前面几种的缺点 缺点主要是服务端代码要特殊处理 而且每次hold住请求一旦请求多了同时hold较多连接的时候 会很耗服务器资源
示例代码在这里 :传送门 只有 组合0-0 与组合 1-1 的实现 且对服务端实现1进行了超时处理