兩年前寫了一篇websocket心跳的博客——初探和實現websocket心跳重連。 閱讀量一直比較大,加上最近考慮寫一個本身的npm包,所以就完成了一個websocket心跳的檢測庫。在這裏先感謝幾個提供幫助的大佬朋友們,小弟受益不淺。html
websocket-heartbeat-js基於瀏覽器js原生websocket封裝,主要目的是保障客戶端websocket與服務端鏈接狀態。該程序有心跳檢測及自動重連機制,當網絡斷開或者後端服務問題形成客戶端websocket斷開,程序會自動嘗試從新鏈接直到再次鏈接成功。前端
在使用原生websocket的時候,若是設備網絡斷開,不會觸發任何函數,前端程序沒法得知當前鏈接已經斷開。這個時候若是調用websocket.send方法,瀏覽器就會發現消息發不出去,便會馬上或者必定短期後(不一樣瀏覽器或者瀏覽器版本可能表現不一樣)觸發onclose函數。node
後端websocket服務也可能出現異常,鏈接斷開後前端也並無收到通知,所以須要前端定時發送心跳消息ping,後端收到ping類型的消息,立馬返回pong消息,告知前端鏈接正常。若是必定時間沒收到pong消息,就說明鏈接不正常,前端便會執行重連。git
爲了解決以上兩個問題,之前端做爲主動方,定時發送ping消息,用於檢測網絡和先後端鏈接問題。一旦發現異常,前端持續執行重連邏輯,直到重連成功。github
1.關閉websocket鏈接web
若是須要斷開websocket,應該執行WebsocketHeartbeatJs.close(),WebsocketHeartbeatJs.ws是原生Websocket實例對象,WebsocketHeartbeatJs.ws.onclose,已經被綁定了重連方法,若是後端websocket服務直接關閉鏈接,前端WebsocketHeartbeatJs.ws.onclose會被執行,WebsocketHeartbeatJs會嘗試重連。若是後端想告訴前端須要斷開鏈接,須要發送特定消息給前端,前端收到特定消息,調用WebsocketHeartbeatJs.close(),WebsocketHeartbeatJs將不會重連。npm
websocketHeartbeatJs.onmessage = (e) => { if(e.data == 'close') websocketHeartbeatJs.close(); }
2.ping & pongjson
前端發送ping消息,後端收到後,須要馬上返回pong消息,pong消息能夠是任何值,websocket-heartbeat-js並不處理pong消息,而只是在收到任何消息後,重置心跳,由於收到任何消息就說明鏈接是正常的。後端
npm install websocket-heartbeat-js
import WebsocketHeartbeatJs from 'websocket-heartbeat-js'; let websocketHeartbeatJs = new WebsocketHeartbeatJs({ url: 'ws://xxxxxxx' }); websocketHeartbeatJs.onopen = function () { console.log('connect success'); websocketHeartbeatJs.send('hello server'); } websocketHeartbeatJs.onmessage = function (e) { console.log(`onmessage: ${e.data}`); } websocketHeartbeatJs.onreconnect = function () { console.log('reconnecting...'); }
<script src="./node_modules/websocket-heartbeat-js/dist/index.js"></script> let websocketHeartbeatJs = new window.WebsocketHeartbeatJs({ url: 'ws://xxxxxxx' });
websocket-heartbeat-js僅僅是封裝了心跳相關的鉤子函數,websocketHeartbeatJs.ws是原生Websocket實例,如須要使用更多websocket特性,請直接操做websocketHeartbeatJs.ws。api
websocketHeartbeatJs.ws 等於 WebSocket(websocketHeartbeatJs.opts.url);
屬性 | 必填 | 類型 | 默認值 | 描述 |
---|---|---|---|---|
url | true | string | none | websocket服務端接口地址 |
pingTimeout | false | number | 15000 | 每隔15秒發送一次心跳,若是收到任何後端消息定時器將會重置 |
pongTimeout | false | number | 10000 | ping消息發送以後,10秒內沒收到後端消息便會認爲鏈接斷開 |
reconnectTimeout | false | number | 2000 | 嘗試重連的間隔時間 |
pingMsg | false | string | "heartbeat" | ping消息值 |
const options = { url: 'ws://xxxx', pingTimeout: 15000, pongTimeout: 10000, reconnectTimeout: 2000, pingMsg: "heartbeat" } let websocketHeartbeatJs = new WebsocketHeartbeatJs(options);
發送消息給後端
websocketHeartbeatJs.send('hello server');
前端手動斷開websocket鏈接,此方法不會觸發重連。 websocketHeartbeatJs.close()
websocketHeartbeatJs.onclose = () => { console.log('connect close'); }
websocketHeartbeatJs.onerror = () => { console.log('connect onerror'); }
websocketHeartbeatJs.onopen = () => { console.log('open success'); }
websocketHeartbeatJs.onmessage = (e) => { console.log('msg:', e.data); }
websocketHeartbeatJs.onreconnect = (e) => { console.log('reconnecting...'); }