Web-IM前端解决方案
2019獨角獸企業重金招聘Python工程師標準>>>
前端MV*設計模式作為SPA(single page application)比較成熟的解決方案,在很多應用場景下被廣泛運用。數據模型驅動的優勢不言而喻,我們可以清晰的劃分服務端數據與交互表現,更多關注前端模塊層級之間的邏輯處理,擁有更好的可維護性和擴展性。然而模塊化的層級結構讓MV*和通常意義上的前端頁面相比顯得非常臃腫,一個MV*的組織架構可以將項目提升到App級別,所以MV*的選用使應用更加系統化的同時也失去了一些靈活性。
Web-IM有著比較明顯映射的數據模型,前有響應用戶的富應用交互模式,后與服務端數據通訊有著多種鏈接模式,模塊結構劃分比較明顯,MV*的使用可以更好的處理這三者之間的關系。
數據模塊,界面模塊這兩個必不可少,考慮到與服務端的通訊涉及到flash socket、ajax poll多套鏈接(將來還可能擴展更多鏈接方式,如websocket),所以把服務端細化到應用接口層,包括socket調用接口、回調接口和控制接口操作的socket交互模塊,由socket交互模塊來實現不同的連接方式,不同連接方式公用調用接口和回調接口,走相同的接口調用,然后加上一個相當于控制器的模塊把前面所有模塊聯系起來,先稱其為通知模塊,負責模塊間的連接,最后再加上前端神級模塊util,我們就可以組裝起一個基于MV*思想的Web-IM。
????/***?MOGU.IM.Data*?@namespace*?@desc?IM數據Model?-?IM數據存儲對象*/MOGU.IM.Data?=?{};/***?MOGU.IM.Interface*?@namespace*?@desc?界面模塊?-?界面構成?&?控制界面現實相關*/MOGU.IM.Interface?=?(function()?{}());/***?MOGU.IM.SocketInteface*?@namespace*?@desc?Socket接口映射?-?向服務端的請求接口*/MOGU.IM.SocketInteface?=?{};/***?MOGU.IM.SocketCallback*?@namespace*?@desc?Socket回調映射?-?接受服務端消息推送的接口*/MOGU.IM.SocketCallback?=?{};/***?MOGU.IM.SocketNotification*?@namespace*?@desc?Socket交互模塊*/MOGU.IM.SocketNotification?=?(function()?{}());/***?MOGU.IM.Notification*?@namespace*?@desc?消息通知模塊?-?控制IM的Model數據變化,發送消息給界面元素顯示*/MOGU.IM.Notification?=?(function()?{}());/***?MOGU.IM.Util*?@namespace*?@desc?IM工具模塊?-?工具函數集合*/MOGU.IM.Util?=?{};看到這里,好像已經實現了邏輯分離,模塊各司其職,組成了一個擁有整體功能的Web-IM,jsdoc把文檔生成下,IM就可以開始投入使用了。在滿足了當前需求的情況下,這樣的設計就是我們蘑菇街的初代Web-IM,沒錯,只是初代...
軟件工程中永遠不變的是需求的變化,下面我們來接受需求的洗禮吧,不,我們換個方向,來一起向前端開心的提需求。
“我們服務端這邊加了登錄驗證,你那邊改一下”
“這里幾個店鋪是系統賬號,不讓用戶回復,只接受消息,就把發送的輸入框界面隱藏下,不需要UI的”
“我們手機這邊要做個wapIM,和web的差不多,在手機客戶端里面用的,功能只有發送接受消息就可以了,應該很快吧”
“怎么轉客服這邊沒提示的,要幫用戶把原來的客服關掉,然后告訴用戶接下來由新的客服來服務”
…
嗯,很熟悉的場景,回來吧,開始做需求了,不急,一個一個來。
登錄驗證,之前設計的SocketNotification用來管理所有鏈接方式的,在這加一下就好了;
系統賬號隱藏輸入框,好吧,在Interface里面加判斷,如果是系統賬號就隱藏掉...怎么代碼看起來又變丑了;
wapIM,還好是模塊劃分的,把Interface層重新寫個wap的好了,誒,好像不對,加過登錄驗證,客戶端的驗證方式和web的驗證方式不同,不是吧,所有的接口都要帶上client參數,在這里寫if代碼沒法看了,哎,拷一份出來好了;
轉客服,還好有數據模型,把Data里面的userlist操作下好了,之前的客服刪掉,新的客服加進來,完了,提示怎么辦…又是一堆煞風景的代碼。
為了提供可維護的jsdoc文檔,之前把模塊都放到一個文件,然后經過一輪一輪的轟炸,我們的代碼達到了
沒錯,4702行,呵呵。
“這里加個東西吧”
“不要改了,改不動了= =。。?!?/p>
程序的臃腫越來越明顯,設計之初的想法不是這樣的,最后達到了無法維護的地步,重構任務急不可待。先總結下之前設計的不足,后面需要考慮和改進的地方有哪些。
首先模塊化最初的想法是好的,但是改來改去,發現模塊里面的額外邏輯越來越多,有時一個功能修改可能牽扯到幾個模塊,模塊功能是獨立了,但是低耦合卻沒做到;
多版本共存時,很多代碼達到了數學幾何中的相似不相同;
為了提供代碼目錄文檔,所有模塊放一個文件中,導致文件過大,無法維護,就算是按興趣命名也得分文件;
和服務端的交互除了socket鏈接外,還有一般的服務端接口(如商品數據查詢etc.),socket模塊雖然獨立了,但是服務端接口分散到各個需要使用的模塊中,沒法統一管理;
服務端和界面所使用的數據模型是同一套,服務端修改數據模型雖然有分操作類別,但是與數據模型直接聯系的界面在模型修改后立馬做出反應,并不區分修改是來自哪種情況(如轉客服提示不能跟著userlist的更改一起通知過來)。
總結新設計的前端架構需要解決以下問題:
項目分文件
模塊解耦合
增加代碼復用
服務層獨立
不同版本只針對interface層
新的模塊大概分成兩大塊。服務層,解決所有和服務端交互的數據處理,自己維護一套數據模型,可以推送數據更改、消息變更。界面層,多版本開發,接受服務層推送數據,實現界面展示和交互功能。基于以上劃分,SDK的解決方案應運而生。
新的目錄層級如下:
im|—?web?//?界面層mvc|?????|—?scripts|?????|?????|—?collection?+|?????|?????|—?helper?+|?????|?????|—?model?+|?????|?????`—?view?+|?????|—?style?+|?????`—?tpl?+|—?wap?+`—?sdk?//?sdk即服務層|—?im-1.1.js?//?sdk接口`—?1.1|—?connect.js?//?鏈接模塊,多套鏈接方式的實現|—?core.js?//?sdk接口中轉|—?data.js?//?數據模塊,包括im運行時的用戶數據和sdk配置數據|—?event.js?//?sdk自定義消息推送模塊|—?inter-local.js?//?sdk本地接口|—?inter-socket.js?//?sdk?socket接口|—?inter-svrs.js?//?sdk服務端接口|—?socket.js?//?socket請求、調用模塊`—?util.js?//?工具函數界面層依舊采用MV*模式,用Backbone來組織結構,不同的是界面層的數據模型完全是展示所用,更新數據從SDK獲取。SDK是和服務端的通信橋梁,維護服務端推送的用戶信息和消息隊列,更新主動查詢的數據,推送相應的數據消息。
參考weibo的JavaScript SDK設計,SDK應該有SDK參數初始化、數據請求這兩個接口??紤]IM的特殊性,對應的登錄驗證其實可以抽象成建立鏈接,數據、消息推送可以抽象成自定義事件監聽。所以SDK提供的接口如下
????/***?@desc?初始化*?@param?{object}?SDK參數*/init:?function(option)?{}/***?@desc?建立連接*?@param?{function}?回調函數*/connect:?function(callback)?{}/***?@desc?數據請求*?@param?{string}?接口名*?@param?{object}?參數*?@param?{function}?回調函數*/parseCmd:?function(cmd,?param,?callback)?{}/***?@desc?自定義事件監聽*?@param?{string}?自定義事件名*?@param?{function}?回調函數*/listen:?function(ename,?callback)?{}由于業務層基本集中于上層界面,只要數據結構不動,相應版本只需建立好鏈接,然后就可以處理自己的業務相關邏輯,不用再關心如何與服務端通訊,相反的,只要是與服務端做的數據修改,只需在sdk層實現就可以實現多版本同時更新,不用擔心代碼冗余帶來的巨大維護成本。SDK接口調用方式如圖
這里包括了除SDK listen接口之外的所有接口,listen接口的使用在上圖的notice模塊中。上面說過數據和消息推送是IM與其他web應用相比特殊性的存在,listen接口正是為了解決推送問題設計的,考慮數據的單向傳遞和低耦合,jQuery里面的自定義事件正好滿足了這兩個需求,對自定義事件做一次簡單的封裝
????/***?@desc?綁定事件*/on:?function(ename,?callback)?{$(document).on(pre?+?ename,?function(e,?data)?{callback?&&?callback(data);});},/***?@desc?觸發事件*/trigger:?function(ename,?data)?{if?(events[ename])?{$(document).trigger(pre?+?ename,?[data]);}}在SDK內部只需要trigger操作就能給外部(界面層)推送消息和數據,在外部實現需要監聽的自定義消息即可,在現在的im中,就是notice模塊的實現
????//?用戶信息更新im.listen('userinfo:update',?function(userinfo)?{});//?用戶列表更新im.listen('userlist:update',?function(usersinfo)?{});//?即時消息im.listen('message:new',?function(msginfo)?{});...至此,SDK的解決方案彌補了之前簡單模塊化的不足,有利于多平臺版本的維護,可以支持服務端協議版本的單獨升級,同時對外開放SDK API也成為可能。
能滿足當時需求的解決方案就是好的解決方案,隨著需求的變化,一層不變必定會帶來巨大的維護成本,Web-IM的解決方案也將不斷完善下去。
轉載于:https://my.oschina.net/bosscheng/blog/338641
總結
以上是生活随笔為你收集整理的Web-IM前端解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国汽车大受俄罗斯消费者欢迎 市场份额暴
- 下一篇: 人工智能,能治工人?曝谷歌等科技巨头用A