前言 參考的 "釘釘調試頁面" 實現,僅供學習! 功能為: __PC端編寫代碼,手機端執行__ 解決的痛點是: __避免了調試 應用時重覆寫各種測試頁面__ 源碼與示例 __源碼__ "https://github.com/dailc/node server examples/tree/master ...
前言
參考的釘釘調試頁面實現,僅供學習!
功能為:
PC端編寫代碼,手機端執行
解決的痛點是:
避免了調試hybrid
應用時重覆寫各種測試頁面
源碼與示例
源碼
https://github.com/dailc/node-server-examples/tree/master/node-socketio-hybriddebug
運行
1.`npm install`
2.`npm run serve`啟動`node`服務
3.瀏覽器打開`./test/debugroom.html`頁面
4.開始測試(瀏覽器直接打開或手機掃碼)
註意,手機端鏈接請確保在同一個網段
註意⚠️,實際情況請重寫client
頁面,讓其支持對於Hybrid
容器的API
示例
原理
原理其實非常簡單,就是HTML5
中的websocket
,而且為了方便,還直接使用了成熟的第三方庫socket.io
基本交互如下:
1.先啟動一個node後臺(控制台),基於`express`和`socket.io`監聽`socket`連接
2.打開一個PC端調試頁面,連接後臺,創建一個房間(可以創建N個房間)
3.PC端頁面基於房間號生成對應房間的客戶端地址(每一個房間中可以有`N`個客戶端),並基於地址創建二維碼,方便使用(可以基於`qrcode.js`等庫)
4.`Hybrid`客戶端掃碼後(或者打開客戶端鏈接後),客戶端頁面連接後臺,根據當前的房間號,在房間中創建客戶端
5.PC端輸入代碼後,點擊執行時,會將代碼文本發送到後臺,然後後臺再推送給客戶端,客戶端通過`eval`即可執行這段代碼,執行完畢後也可通過同樣方式通知PC端
需要註意的是:
服務端是引用的
npm
的socket.io
包客戶端是引用socket.io-client項目中發佈的
socket.io.js
文件
另外:
後臺程式直接基於
es6
語法編寫的,然後基於gulp
打包成dest
文件,實際運行的是dest
中的發佈文件,代碼規範接近與airbnb
前端頁面的話比較隨意,樣式還大量用了釘釘原本的樣式,也沒有考慮各種瀏覽器的相容
為什麼說是
hybrid
調試頁面?因為打造它的核心需求就是用來調試hybrid
API
步驟
由於篇幅關係(也沒有必要),並不會將所有代碼都介紹一遍,只會介紹一些重點步驟,更多的可以直接閱讀源碼(源碼中已經足夠清晰)
設計DebugRoom
(PC端)和DebugClient
(hybrid
端)
根據交互,PC端和hybrid端都需要和後臺連接,因此這裡直接單獨封裝了兩個類
DebuRoom類
房間的定義是:
只有一個
socket
引用有一個房間
id
標識房間內可以管理客戶端(增,刪,查)
class DebugRoom {
// 所屬的房間號
this._roomId
// 所持有的socket對象
this._socket
// 客戶端持有預設是一個空對象,key是clientid,value是client
this._clients
id()
clients()
socket()
getClientsCount()
removeClient(client)
addClient(client)
clearClients()
}
DebugClient類
客戶端的定義是:
只有一個
socket
引用有一個客戶端
id
標識有一個房間
id
引用,指向對於的房間號(當然其實也可以是引用DebugRoom
對象的)
class DebugClient {
// 所屬的房間號
this._roomId
// 客戶端id
this._clientId
// 所持有的socket對象
this._socket
id()
roomId()
socket()
}
設計一些交互介面
前後端交互通過socket.io
中定義的事件來,以下是房間以及客戶端和後臺的交互事件介面
通用交互事件
後臺:
// 後臺監聽連接,每有一個連接時(前端通過`io.connect`),會通知客戶端觸發'open'事件
io.on('connection', ...)
// 後臺監聽關閉連接,每當連接關閉時(前端直接關閉或調用`socket.disconnect`),會檢測本地房間與客戶端,如果關閉的是客戶端,則移除這個客戶端,對於的房間下的引用也置空,否則如果是房間,移除並關閉房間內所有的客戶端
io.on('disconnect', ...)
房間與客戶端:
// 前臺監聽打開事件,此時,如果是房間,則會通知後臺觸發'create room',否則通知後臺觸發'create client'
socket.on('open', ...)
// 前臺監聽連接是否關閉
socket.on('disconnect', ...)
房間與後臺交互事件
後臺:
// 監聽創建房間,如果房間ID合法,則會創建一個新的房間(new DebugRoom)
io.on('create room', ...)
// 監聽房間分發數據,並且將數據轉發給房間內的所有客戶端,通知客戶端觸發'receive dispatch data'事件
io.on('dispatch data', ...)
房間:
// 監聽客戶端創建,每一個客戶端加入對應房間時都會通知這個房間
socket.on('client created', ...)
// 監聽客戶端關閉,每一個客戶端退出時都會通知這個房間
socket.on('client destroy', ...)
// 監聽客戶端執行,客戶端每執行一次分發數據時,都會通知房間是否執行成功
socket.on('client excuted', ...)
客戶端與後臺交互事件
後臺:
// 監聽客戶端創建,如果房間已存在,並且客戶端id合法,才會正常創建,創建完後會通知房間觸發'client created'事件
io.on('create client', ...)
// 監聽客戶端響應執行,客戶端執行一次分發數據後,會通知後臺,後臺接收到這個事件後,通知房間觸發'client excuted'事件
io.on('client excute notify', ...)
客戶端:
// 監聽接收分發數據,接收完後會執行數據中的代碼,並且通知後臺是否執行成功,觸發後臺的'client excute notify'事件
socket.on('receive dispatch data', ...)
一些邏輯上的細節
以上流程就是整套程式的基本思路與交互,這裡再補充一些交互細節
用全局的
roomsHash
和clientsHash
緩存住所有的房間和客戶端,方便直接查詢每次創建時,
id
可以直接綁定在對於的socket
中,這樣更方便房間和客戶端
id
最好不要直接使用,可以進過一次編碼(這樣可以直接使用中文)客戶端失聯時,一定要先判斷房間是否以及銷毀,不要重覆操作
失去連接後,緩存中的引用要及時清除
更多源碼請參考https://github.com/dailc/node-server-examples/tree/master/node-socketio-hybriddebug