小程序版 websocket 聊天室。 從服務器到小程序客戶端配置基礎教程。
在本教程內我們將在小程序內實現一個基本的 websocket 聊天室, 計劃實現以下功能:
小程序已掛,原因是個人開發者無法提交信息交流類小程序, 不過在本地運行 demo 還是沒問題的。
寫的有紕漏的地方還請大家指出,在 SF 下留言或在 本項目 git 內提 issue ,我們一起進步 ^o^
小程序端的聊天室信息流其實非常簡單, 而本教程就借助一個好玩兒的小程序聊天室來進一步理解小程序中的 session 實現。
我在服務器端環境搭建及配置主要參考騰訊云實驗 基于 CentOS 搭建微信小程序服務
我們在此先要理解小程序端為何無法實現 session, 以及如何在小程序實現 websocket 通信。
小程序并非嵌套在微信內的 html5 網頁, 它并不是從 url 訪問到的。 我們只能自己實現類似會話的東西, 好在官方已經提供了相應的套件來實現 session。 即 wafer-client-sdk 和 node 中間件 wafer-node-session , 我們依照文檔就能簡單地實現 session。
騰訊云 wafer 項目下有很多相似項目「大部分需要配合騰訊云進行一鍵部署」, 如果我們只需要實現小程序 session 管理的話, wafer-client-sdk 和 node 中間件 wafer-node-session 即可。
在服務器端我們使用了 ws 包來實現 websocket ,沒有使用 socket.io 的原因是 socket.io 需要客戶端有額外的腳本才能實現通信。
在小程序端我們引入 wafer-client-sdk 套件使服務器可以獲取 session。
主要邏輯分為幾個簡單函數, 當然你需要先配置請求的服務器域名和小程序賬號密碼。
// 引入 session 套件, 里面封裝了 wx.login, wx.getUserInfo 等操作 const wafer = require('../../vendors/wafer-client-sdk/index') // 用于登錄使服務器獲得 session, 然后服務器返回的 session 里就會包含用戶信息了, 用來在 websocket 里返回發信息用戶的頭像 url function login(){ ..... } // 用于有新信息時更新數據, msg 指信息, ad 指 websocket 傳回的信息 id, 用于 scroll-into-view 滾動 pushMsg(msg, ad) { ..... } // 用于監聽 websocket 連接 listen(){ ..... } // 用于小程序發送 websocket 信息 send(){ ..... }
基本就是這些, 關于 websocket 通信過程是這樣的:
當然最開始是要與服務器端 websocket 連接的, 只有每個連接了的客戶端才可以交流信息。
對于 session 的實現我們在服務器端使用了 wafer-node-session 即為連接提供 session 能力。 在小程序端我們配套使用了 wafer-client-sdk , 這里面封裝了 wx.request、 wx.login 等邏輯, 實現了小程序端的用戶登錄、session 設置。
關于小程序端的 session 獲取問題主要有如下幾個步驟
在我們的 demo 中就出現了服務器 session 已經過期而本地 session 還沒過期的情況。 而 websocket 每次發送信息都需要從 req.session 內獲取用戶頭像, 所以會導致 websocket 連接失敗。 但是在小程序端 session 未過期,即在服務器端的 sessionKey 和小程序的 sessionKey 不一致了 「客戶端 sessionKey 還在而服務器的 sessionKey 已經過期銷毀」, 導致比對失敗。 那怎么辦呢? 重新請求唄! 但是因為 wafer 封裝了 session 管理 「小程序端 session 過期后才會重新請求」 存在 session 緩存的緣故, 小程序并沒有重新發送信息給自己的服務器進而生成新的 sessionKey, 所以我們在每一次 wx.sendSocketMessage 發信息的時候都要檢查服務器端的 session 情況, 這里需要做簡單的判斷「websocket 信息有錯誤就清除本地 session」讓小程序重新請求服務器。
既然要發送信息「即產生數據」, 那么這些信息都儲存在哪里呢? 在發送文本信息時, 服務器端收到數據后只做簡單地處理便返回給小程序, 這時的數據應該是儲存在服務器內存中。 因為 websocket 在收到請求后簡單處理了字符串信息直接返回給小程序, 那我們發送其它富媒體信息時,也可以以二進制的方式發送給 websocket 服務器, 然后重新返回給客戶端 「即 websocket 只做文件中轉」,相關實現 websocket-stream 。 貌似看起來很復雜,在這里我使用了國內的 paas 服務商 leanCloud 的儲存服務 「即小程序端把發送的文件儲存在云端,返回一個文件地址」,然后我們把這個文件信息進行標注「即只發送文件的 url 信息, 小程序端判斷請求是否是文件進而顯示」。 當然你也可以發送視頻或者音頻, 把他們都保存在云端, 只發送其相應的 url 即可。 我們這里的 websocket 服務器只做一個文件中轉的功能, 而文件的存儲交給云端來負責。