在《閃電提速》的博客中我提到了用socket.io 替換原來的連接方式代箭,本章就如何引入socket.io的細節(jié)做進一步闡述。
主要的內(nèi)容如下:
1涕刚、WebSocket 簡介
2嗡综、為什么要用socket.io
3、如何用socket.io
4杜漠、后續(xù)安排
一极景、WebSocket簡介
如果您對websocket協(xié)議不太熟悉,可以通過這兩個鏈接先了解一下驾茴。
WebSocket詳解(一):初步認識WebSocket技術
WebSocket 是什么原理盼樟?為什么可以實現(xiàn)持久連接?
我簡單提一些吧锈至。Ajax之所以重要晨缴,從本質(zhì)來說,它避免了許多原本需要在Web應用中處理的數(shù)據(jù)傳遞和渲染開銷峡捡。但它有一個先天的缺陷击碗,就是無法控制服務器端接受請求的先后順序筑悴!同時,在TCP傳輸信息時延都,信息頭的數(shù)據(jù)量有時遠遠超過了真正要發(fā)送的數(shù)據(jù)量雷猪。
HTML5給我們一個解決方案,就是WebSocket晰房!WebSocket是web下的TCP求摇,一個底層雙向的socket,容許用戶對信息傳遞進行控制殊者。
WebSocket是建立在HTML協(xié)議之上与境,但它和HTML的區(qū)別是,在握手之后猖吴,客戶端和服務器就建立了類似TCP Socket通道摔刁,為了更好地理解,看下面的圖示:
node.js實現(xiàn)WebSocket的demo很多海蔽,如果有時間共屈,可以簡單搜一下。不看也沒什么大不了的党窜,記住塔哥這句話拗引,websocket就是個雙向數(shù)據(jù)通道,看懂下一章沒問題的幌衣。
二矾削、為什么要用socket.io
WebSocket有它誘人的一面,但現(xiàn)實中瀏覽器的使用情況給前端開發(fā)帶來巨大的難題豁护。塔哥寫了好多年C++哼凯,只要動態(tài)庫的依賴關系整明白了,幾乎所有的windows系統(tǒng)都沒問題楚里,但在前端開發(fā)中就沒那么幸運了断部。
Socket.IO的出現(xiàn)就是為了解決這個問題班缎,它的特征之一就是消息的傳遞是基于傳輸?shù)暮猓侨恳蕾嘩ebSocket,也就是說吝梅,Socket.IO可以在絕大多數(shù)瀏覽器上運行虱疏,尤其是對iOS的支持惹骂。這也是我選擇Socket.IO的原因苏携。
在Web世界,更多的通信方式是依賴請求與應答对粪。但在協(xié)同領域右冻,更多的是基于“事件”的傳輸装蓬。Socket.IO通過:
? 分發(fā)(emit)
? 監(jiān)聽(listen)
事件來進行數(shù)據(jù)的傳輸,我們抓一下石墨文檔(這是我非常喜歡的一個國內(nèi)產(chǎn)品)纱扭,能看到它的協(xié)同通信方式就是用的socket.io牍帚。
好了,我的鋪墊也不少了乳蛾,該回答為什么我在together.js中引入socket.io:
- 因為使用socket.io后暗赶,這個協(xié)同產(chǎn)品能在更多的平臺下運行;
- Socket.IO在git上有4K多個Star肃叶,運行穩(wěn)定蹂随、文檔齊全;
三因惭、怎么引入socket.IO
打鐵還需自身硬岳锁,多見識多練,坑踩多了蹦魔,闖江湖就沒什么可怕的了激率。這一章我寫之前還是猶豫過的,因為socket.IO我也是第一次用勿决,寫不好露怯是小事乒躺,主要還是怕把您給耽誤了。后來覺得剥险,還是寫吧聪蘸,寫的過程也是一個成長的過程。還是那句話表制,如果有不妥的地方健爬,還望您指證。我先行謝過 :)
引入socket.IO的工作我分兩部分介紹么介,先服務端再客戶端娜遵。
3.1 TJS的服務器端改造
together.js 的服務器端代碼是在hub目錄下,它實現(xiàn)了:
? websocket的創(chuàng)建與生命周期管理壤短;
? 狀態(tài)維護與消息的派發(fā)设拟;
寫的怎么說呢,也許是我始終沒理解作者的思路久脯,端詳好幾回也不知道從哪下手纳胧,干脆重新寫吧。所以說帘撰,在優(yōu)化的過程中跑慕,websocket的服務器端代碼我放在了“devserver.js”里,node直接啟動,拋棄了原有hub/server.js核行。
主要內(nèi)容是:
3.2 TJS的客戶端改造
客戶端引入socket.io就容易多了,還是以Tinymce這個demo來說芝雪,下圖就是index.html中引入socket.io.js的方法减余。
然后替換channels.js中原有websocket實現(xiàn)方式,具體內(nèi)容有兩步:
1) _setupConnection()
_setupConnection: function () {
if (this.closed) {
return;
}
//connect socket.IO
this.hSocket = io();
//設置缺省用戶狀態(tài)
this.hSocket.emit('add user', "zout" , "001");
//各種事件接收
this.hSocket.on('app.draw', (data) => this._incoming(data));
this.hSocket.on('form-update', (data) => this._incoming(data));
this.hSocket.on('form-init', (data) => this._incoming(data));
this.hSocket.on('app.init', (data) => this._incoming(data));
this.hSocket.on('hello', (data) => this._incoming(data));
}
2) _setupConnection()
_send: function (vType , data) {
this.hSocket.emit(vType ,data);
},
這樣一來惩系,socket.io就融入TJS位岔,同時給TJS帶來速度上的飛躍是非常非常明顯的。
四堡牡、關于后續(xù)安排
在我看來赃承,替換socket.io以后的維護主要還是服務端消息的分發(fā),如果按照現(xiàn)有的邏輯悴侵,每增加一個事件都要做相應的修改瞧剖,太low了!
我的想法是結(jié)合“指令精簡”可免,把事件進行分類抓于,不同類型的事件有自己的消息中轉(zhuǎn)。這樣的話事件相互是獨立的浇借,對研發(fā)與部署都有利捉撮。