最近在做前端頁面渲染的時候,有的組件需要跟隨數據的變化而實時的變化,例如:一個線上報名系統,總人數有一定限制,所以要實時的展現已經報名的人數,應該怎么實現呢?最基本解決思路如下:
技術方案:
1.Ajax輪詢
2.Ajax長輪詢
3.WebSocket
Ajax輪詢
實現簡單,利用XHR,通過setInterval定時向后端發送請求,優點是,實現非常簡單;缺點是會造成數據在一小段時間內不同步和大量無效的請求,增加后端處理壓力.
setInterval(function() {
$.ajax({
url: 'https://www.baidu.com/',
success: function() {
//success code
}
});
}, 3000);
Ajax長輪詢
在Ajax輪詢的基礎上做的一點改進,在后端數據沒有更新的時候不再返回空響應,而且后端一直保存連接,直到后端有數據變化,則相應請求並且關閉連接,前端收到數據,馬上再次向后端發起請求,並處理剛剛收到的數據.
function async() {
$.ajax({
url: 'http://api.3g.qq.com',
success: function() {
async();
//success code
}
});
}
WebSocket
WebSocket是html5出來的東西(協議),也就是說http協議沒有變化,或者說沒關系,但http是不支持久鏈接的,WebSocket其實是一個新協議,跟http協議基本沒有關系,只是為了兼容現有瀏覽器的握手規范而已。
WebSocket
通信協議包含兩個部分,一是開放性HTTP
握手連接協商連接參數,二是二進制消息分幀機制(接收消息的文本和二進制數據傳輸)。它是一個獨立完善的協議,也可以在瀏覽器之外實現。
HTTP升級協商
WebSocket
協議提供了很多強大的特性:基於消息的通信、自定義的二進制分幀層、子協議協商、可選的協議擴展,等等。即在交換數據之前,客戶端必須與服務器協商適當的參數以建立連接。
利用HTTP
完成握手有幾個好處。首先,讓WebSockets
與現有HTTP
基礎設施兼容:WebSocket
服務器可以運行在80和443 端口上,這通常是對客戶端唯一開放的端口。其次,讓我們可以重用並擴展HTTP
的Upgrade
流,為其添加自定義的WebSocket
首部,以完成協商。
請求頭信息
Connection:Upgrade Sec-WebSocket-Key:eDCPPyPQZq7PiwRcx8SPog== Sec-WebSocket-Version:13 Upgrade:websocket
響應頭信息
HTTP/1.1 101 Switching Protocols Connection:Upgrade Sec-WebSocket-Accept:/ZVAP3n6XuqDUoDp416PYUO+ZJc= Upgrade:websocket
最后,前述握手完成后,如果握手成功,該連接就可以用作雙向通信信道交換WebSocket
消息。到此,客戶端與服務器之間不會再發生HTTP
通信,一切由WebSocket
協議接管。
具體使用方法,本文采用node.js中的Socket.IO來進行說明:
1.服務端創建socket.io的實例
var app = require('express')();
var http = require('http').Server(app);
//創建實例
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendfile('index.html');
});
//監聽前端連接
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
前端創建websocket連接:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
2.數據傳輸
前端向后端發送數據:
socket.emit('chat message', $('#m').val());
后端接收數據:
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
});
});
----------------------------------------------------------------------------------------------------------------------------------
后端向前端發送數據:
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
前端接收數據:
socket.on('chat message', function(msg){
console.log(msg);
});