基於socket.io打造hybrid除錯頁面

dailc發表於2019-02-21

前言

參考的釘釘除錯頁面實現,僅供學習!

功能為:

PC端編寫程式碼,手機端執行

解決的痛點是:

避免了除錯hybrid應用時重複寫各種測試頁面

原始碼與示例

原始碼

github.com/dailc/node-…

執行

1.`npm install`

2.`npm run serve`啟動`node`服務

3.瀏覽器開啟`./test/debugroom.html`頁面

4.開始測試(瀏覽器直接開啟或手機掃碼)

注意,手機端連結請確保在同一個網段複製程式碼

注意⚠️,實際情況請重寫client頁面,讓其支援對於Hybrid容器的API

示例

image
image

image
image

原理

原理其實非常簡單,就是HTML5中的websocket,而且為了方便,還直接使用了成熟的第三方庫socket.io

基本互動如下:

1.先啟動一個node後臺(控制檯),基於`express``socket.io`監聽`socket`連線

2.開啟一個PC端除錯頁面,連線後臺,建立一個房間(可以建立N個房間)

3.PC端頁面基於房間號生成對應房間的客戶端地址(每一個房間中可以有`N`個客戶端),並基於地址建立二維碼,方便使用(可以基於`qrcode.js`等庫)

4.`Hybrid`客戶端掃碼後(或者開啟客戶端連結後),客戶端頁面連線後臺,根據當前的房間號,在房間中建立客戶端

5.PC端輸入程式碼後,點選執行時,會將程式碼文字傳送到後臺,然後後臺再推送給客戶端,客戶端通過`eval`即可執行這段程式碼,執行完畢後也可通過同樣方式通知PC端複製程式碼

需要注意的是:

  • 服務端是引用的npmsocket.io

  • 客戶端是引用socket.io-client專案中釋出的socket.io.js檔案

另外:

  • 後臺程式直接基於es6語法編寫的,然後基於gulp打包成dest檔案,實際執行的是dest中的釋出檔案,程式碼規範接近與airbnb

  • 前端頁面的話比較隨意,樣式還大量用了釘釘原本的樣式,也沒有考慮各種瀏覽器的相容

  • 為什麼說是hybrid除錯頁面?因為打造它的核心需求就是用來除錯hybridAPI

步驟

由於篇幅關係(也沒有必要),並不會將所有程式碼都介紹一遍,只會介紹一些重點步驟,更多的可以直接閱讀原始碼(原始碼中已經足夠清晰)

設計DebugRoom(PC端)和DebugClienthybrid端)

根據互動,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', ...)複製程式碼

一些邏輯上的細節

以上流程就是整套程式的基本思路與互動,這裡再補充一些互動細節

  • 用全域性的roomsHashclientsHash快取住所有的房間和客戶端,方便直接查詢

  • 每次建立時,id可以直接繫結在對於的socket中,這樣更方便

  • 房間和客戶端id最好不要直接使用,可以進過一次編碼(這樣可以直接使用中文)

  • 客戶端失聯時,一定要先判斷房間是否以及銷燬,不要重複操作

  • 失去連線後,快取中的引用要及時清除

更多原始碼請參考github.com/dailc/node-…

附錄

參考資料

相關文章