摘要:結合與的發布訂閱模式實踐本文初衷最近恰好在公司做了一個聊天室系統,所以在系統中做了一下對進行的化改造,所以想寫篇文章總結一下,如果大家有什么更好的方法或者心得感悟,歡迎交流技術??紤]到對并沒什么本質影響,所以本文就不涉及了業務場景基于的聊天
結合promise與websocket的發布/訂閱模式實踐 本文初衷
最近恰好在公司做了一個聊天室系統,所以在系統中做了一下對websocket進行的promise化改造,所以想寫篇文章總結一下,如果大家有什么更好的方法或者心得感悟,歡迎交流
技術棧dva + protobuf
考慮到protobuf對websocket并沒什么本質影響,所以本文就不涉及了
基于websocket的聊天室系統
開發痛點可能存在按順序觸發的請求
eg. 刪除req---確認刪除rsp---刷新頁面req---刷新頁面rsp
但由于并非所有的刪除操作后都會刷新頁面,所以考慮是不是可以使用發布訂閱模式來模擬類似promise的流式操作
存在同一類型請求短時間內多次觸發時,如何尋找每一條回復信息的發射源,考慮可以使用promise池+唯一識別碼token來實現
由于dva的異步操作是基于redux-saga的,所以如果可以用promise完成與websocket的互動,那么對于effects中使用yield控制異步流程,也會是一個很好的體驗
實現原理首先,這一套系統的一切前提是請求的唯一標識符token,前端發送給服務器之后,服務器必須要把這個token跟數據放在一起發回來才行
本系統的實現原理是
對websocket的send方法進行封裝 發送階段 1. send執行時,先生成一個promise,及其唯一token 2. 將promise的resolve, reject,token,及其他需要的信息放入一個對象,然后推入一個promise池中 3. 執行websocket的send方法 4. return 這個promise 接收階段 1. 收到回復消息時,先從promise池中對token進行匹配 2. 根據回復的狀態決定執行resolve或reject 3. 其他需要的操作實現代碼
// 每一個實例都只能open一條socket線路,用鎖機制防止重復open // 本例中不使用心跳檢測,為了方便,只要close是非主動觸發且前端能捕捉到的(如瀏覽器主動斷開,服務器主動斷開),都會進行自動重連 export class MyWebSocket { constructor(url) { this.url = url; // close來源判斷及后續操作 this.closeConfig = { resolve: null, closing: false } // promise池 this.promisePool = []; } tokenCheck(req, rsp) { // 此處根據自己的數據結構進行tokenCheck的判斷,返回一個boolean } open() { return new Promise((resolve, reject) => { if (typeof this._websocket === "undefined") { this._websocket = new WebSocket(this.url); this._websocket.open = (e) => { resolve({e, ws: this}); }; this._websocket.onerror = (e) => { reject(e); } } this._websocket.onclose = (e) => { // 非主動close if (!this.closeConfig.closing) { console.log("reconnect"); // 對應的重連操作 } // 若手動close,恢復初始狀態 this.closeConfig.closing = false; } this._websocket.onmessage = (e) => { this.promisePool = this.promisePool.filter((item) => { if (this.tokenCheck(req, rsp) { req.resolve(rsp); return false; } return true; }) }; }); } close() { this.closeConfig.closing = true; this._websocket.close(); } // token包含在content中 send(name, content) { return new Promise((resolve, reject) => { this.promisePool.push({ content, resolve, reject, name }); this._websocket.send({name, content}); }); }
大概流程就是這樣,具體的樣例如下
*test () { const ws = new MyWebSocket("www.mywebsocket.com"); yield ws.open(); yield ws.send(.....).then(()=>{...}); yield ws.send(.....).then(()=>{...}); }
本文呢大概就是這么多了,如果有什么錯誤或者遺漏的地方還請大家多多指教
v0.0.2采取了評論大佬的建議,將promise池從數組改為對象,直接將token做為key,查詢起來也非常方便
export class MyWebSocket { constructor(url) { this.url = url; // close來源判斷及后續操作 this.closeConfig = { resolve: null, closing: false } // promise池 this.promisePool = {}; } tokenCheck(req, rsp) { // 此處根據自己的數據結構進行tokenCheck的判斷,返回一個boolean } open() { return new Promise((resolve, reject) => { if (typeof this._websocket === "undefined") { this._websocket = new WebSocket(this.url); this._websocket.open = (e) => { resolve({e, ws: this}); }; this._websocket.onerror = (e) => { reject(e); } } this._websocket.onclose = (e) => { // 非主動close if (!this.closeConfig.closing) { console.log("reconnect"); // 對應的重連操作 } // 若手動close,恢復初始狀態 this.closeConfig.closing = false; } this._websocket.onmessage = (e) => { const key = e.content.token; const req = this.promisePool[key] req.resolve(e); delete this.promisePool[key]; }; }); } close() { this.closeConfig.closing = true; this._websocket.close(); } // token包含在content中 send(name, content) { return new Promise((resolve, reject) => { this.promisePool[content.token] = { content, resolve, reject, name }; this._websocket.send({name, content}); }); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94995.html
摘要:我在工程實踐中直接使用類作為對應實體類的。因此我的結論是,此庫并不適用于我的工程實踐。工程實踐中對其應用方式的考慮在的官方教程中建議針對每請求創建新的實例,查詢請求結束則實例們的生命周期結束。 因為自己寫過基于react的前端應用,因此一看到GraphQL就被深深吸引,真是直擊痛點啊!服務端開發一直是基于java, Spring的,因此開始研究如何在現有工程框架下加入graphql的支...
摘要:站點接收到請求后,對請求進行驗證,并確認是受害者的憑證,誤以為是無辜的受害者發送的請求。函數內部語句返回的值,會成為方法回調函數的參數。 記錄我最近面試缺漏的知識點 css 1.bootstrap如何實現手機PC端自適應 媒體查詢 2.flex布局 父容器:(記得常用屬性) display:flex flex-direction: row | row-reverse | column ...
摘要:該區域代表可以被所控制的畫布。那么現在第二個問題,識別該文檔,這或許不是大部分用戶的需求,但小部分用戶并不意味著人數少。因此一個基于的請求于標準內提出。 前言 作為程序員,技術的落實與鞏固是必要的,因此想到寫個系列,名為 why what or how 每篇文章試圖解釋清楚一個問題。 這次的 why what or how 主題:現在幾乎所有人都知道了 HTML5 ,那么 H5 到底相...
閱讀 1505·2021-11-22 09:34
閱讀 3320·2021-09-29 09:35
閱讀 562·2021-09-04 16:40
閱讀 2912·2019-08-30 15:53
閱讀 2582·2019-08-30 15:44
閱讀 2584·2019-08-30 14:10
閱讀 1328·2019-08-29 18:43
閱讀 2205·2019-08-29 13:26