做小程序專案的時候有實時通訊的需求,這裡就整理一下 WebSocket 的知識
關於 WebSocket#
- 前言:Web 應用的資訊交互過程一般是客戶端通過瀏覽器發出一個請求,伺服器端接收完請求後進行處理並且返回結果給客戶端,然後客戶端瀏覽器解析資訊,這樣的機制對於實時要求比較高的應用來說就有很大的受限了,因此需要有一種高效節能的雙向通訊機制來保證資料的實時傳輸,WebSocket 應運而生
- 概念:
- MDN: WebSocket 是一個可以創建和伺服器間進行雙向會話的高級技術,通過這個 API 你可以向伺服器發送消息並接受基於事件驅動的響應,這樣就不用向伺服器輪詢獲取資料了
- WebSocket 有 web TCP 之稱,顧名思義是用來通訊的,作為 HTML5 中新增的一種通訊協議,由 TCP 協議與編程 API 組成,可以在瀏覽器與伺服器之間建立雙向連接,以基於事件的方式,賦予瀏覽器原生的實時通訊能力,從而擴展我們的 web 應用,提升應用性能與用戶體驗
- 為什麼使用:
在 WebSocket 出現之前有一些其他的實時通訊方案,比如輪詢、長輪詢、伺服器發送事件- 輪詢 (Polling):客戶端以一定的時間間隔向伺服器發送請求,通過頻繁請求的方式來保持客戶端和伺服器端的資料同步。通常採取
setInterval
或者setTimeout
實現。問題:客戶端以固定頻率向伺服器端發送請求時,伺服器端的資料可能並沒有更新,這樣很多請求就是沒有必要的,浪費頻寬,低效率 - 長輪詢 (Long Polling):對定時輪詢的改進和提高,當伺服器端沒有資料更新的時候,連接會保持一段時間周期直到資料或狀態改變或者時間過期,以此減少無效的客戶端與伺服器間的交互。問題:如果服務端的資料變更非常頻繁的話,與定時輪詢比較起來沒有本質上性能的提高
- 伺服器發送事件 (Server-Sent Event):是 HTML5 規範的一個組成部分,可以實現伺服器到客戶端的單向資料通信,通過 SSE,客戶端可以自動獲取資料更新,而不用重複發送 HTTP 請求。問題:只支持到伺服器到客戶端單向的事件推送,而且所有版本的 IE 都不支持 SSE
- WebSocket:在流量與負載量增大的情況下,相比於傳統的 Ajax 輪詢方案有極大的性能優勢,在開發方面也不算複雜,只需要實例化 WebSocket 創建連接,成功後就可以發送相應消息了
- 輪詢 (Polling):客戶端以一定的時間間隔向伺服器發送請求,通過頻繁請求的方式來保持客戶端和伺服器端的資料同步。通常採取
Node 實現#
這裡採用 Node 的 ws 庫來實現簡單的 WebSocket 伺服器
- 伺服器:
var WebSocketServer = require("ws").Server;
var wss = new WebSocketServer({
port: 3001
});
wss.on("connection", function(ws) {
ws.on("message", function(msg) {
console.log(msg);
ws.send("Nice to meet you!");
});
ws.on("close", function() {
console.log("Stop client");
});
});
- 小程序客戶端:
wx.connectSocket({
url: '伺服器的連結:3001',
data: {},
header: {
'content-type': 'application/json'
},
method: 'GET',
success: function() {
console.log("客戶端連接成功");
}
}),
wx.onSocketOpen(function() {
console.log("WebSocket連接已打開");
wx.sendSocketMessage({
data: 'Hello!'
});
}),
wx.onSocketMessage(function(msg) {
console.log("接收到:"+ msg);
});
這裡特別提一下wx.onSocketMessage()
,因為它只接收字串和二進制類型的資料,因此如果需要發送 json 格式的資料就需要轉換一下,只要是支持 WebSocket 肯定支持原生 window.JSON,所以可以直接使用 JSON.parse () 和 JSON.stringify () 來轉換
這樣一個雙向通訊的實例基本就完成了