Web跨瀏覽器進(jìn)程通信(Web跨域)
在之前一篇文章里嘗試了跨瀏覽器的數(shù)據(jù)共享,最后提到使用LocalConnection還可以實(shí)現(xiàn)跨瀏覽器消息交互的可行性。
花了兩個(gè)晚上簡(jiǎn)略的研究了下,LocalConnection的單向通信非常的簡(jiǎn)單,不過(guò)要實(shí)現(xiàn)多個(gè)終端交互,必須自己實(shí)現(xiàn)一套消息機(jī)制,見(jiàn)智見(jiàn)仁了。
為了簡(jiǎn)單演示,本例使用了基于廣播的觀察者模式:每個(gè)終端可以訂閱自己感興趣的主題,也可以向廣播發(fā)送消息,通知其他感興趣的終端。
Demo: http://www.etherdream.com/FunnyScript/WebIPC/ (多開(kāi)幾個(gè)瀏覽器頁(yè)面小窗口,即可測(cè)試)
比較遺憾的是最新版的Chrome瀏覽器仍然無(wú)法和其他瀏覽器進(jìn)程交互:(
如果沒(méi)有錯(cuò)誤發(fā)生,應(yīng)該就是如下的效果:
在任何一個(gè)頁(yè)面上的操作,都會(huì)立即同步到其他頁(yè)面里,只要Observe了感興趣的主題。
為什么要使用觀察者模式呢?因?yàn)榭邕M(jìn)程的通信是比較耗資源的,所以不感興趣的消息可以直接不訂閱,而不是收到再放棄。
LocalConnection是為單一的通信設(shè)計(jì)的,雖然使用很簡(jiǎn)單,但可用的接口少之又少。想直接用它來(lái)廣播事件,或者消息路由,門(mén)都沒(méi)有。
因此底層的消息發(fā)送上沒(méi)有太多可選余地,只能簡(jiǎn)單的點(diǎn)對(duì)點(diǎn)發(fā)送。我們必須創(chuàng)建多個(gè)LocalConnection,來(lái)實(shí)現(xiàn)消息的匯聚和分發(fā)。
LocalConnection真正能用的只有兩個(gè)方法:
connect(name) —— 創(chuàng)建管道(每個(gè)LocalConnection只能創(chuàng)建一個(gè)管道,每個(gè)管道名只能有一個(gè))
send(name, ...) —— 向管道發(fā)送數(shù)據(jù)
如果只有兩個(gè)終端通信,那么一切都是那么簡(jiǎn)單。。。
只需簡(jiǎn)單的將消息發(fā)送給對(duì)方即可。
不過(guò)有多個(gè)終端情況就大不相同了。由于我們是本地進(jìn)程間通信,并沒(méi)有第三方服務(wù)器主持,加上LocalConnection只能點(diǎn)對(duì)點(diǎn)的發(fā)送消息。意味著每次廣播都要給其他所有的終端都發(fā)送一次,這樣復(fù)雜度就大大增加了。
為了簡(jiǎn)化結(jié)構(gòu),我們模擬一個(gè)LocalConnection作為Host,在第一次啟動(dòng)時(shí)運(yùn)行。其余的作為Client,每次廣播消息都提交給Host,由它來(lái)調(diào)度。
Host維護(hù)著一個(gè)回調(diào)列表。當(dāng)Client對(duì)某個(gè)主題(subject)感興趣時(shí),可以發(fā)送<主題ID,自己的管道名>給Host來(lái)訂閱。于是Host就把此Client的管道名添加到該主題的回調(diào)列表里。以后若有該主題的消息,即可根據(jù)回調(diào)列表通知訂閱的Client。
為了能讓Host和Client通信更簡(jiǎn)單,這里使用channel+ID的命名規(guī)則,來(lái)創(chuàng)建管道名。
Host的ID為空,于是Client發(fā)送數(shù)據(jù)只需send(channel)即可;
Client的ID從1~100,選一個(gè)沒(méi)用被占用的作為管道名。Host回調(diào)時(shí)只需send(channel+id)就能通知對(duì)應(yīng)的Client。
然而,這個(gè)Host服務(wù)僅僅是假象的。我們根本沒(méi)法在頁(yè)面之外運(yùn)行一個(gè)第三方服務(wù),一切只能在頁(yè)面中實(shí)現(xiàn)!于是我們把第一次啟動(dòng)的頁(yè)面作為Host。當(dāng)這個(gè)頁(yè)面關(guān)閉時(shí),我們?cè)偻ㄖ诙€(gè)頁(yè)面創(chuàng)建Host,以此類(lèi)推。。。
由于沒(méi)有第三方服務(wù)器,每個(gè)Client都可以兼職做Host。到這里,你是不是想到了局域網(wǎng)游戲?由于沒(méi)有服務(wù)器,第一個(gè)創(chuàng)建的玩家便是主機(jī)。當(dāng)他退出時(shí),主機(jī)就交給了第二個(gè)玩家。如果他沒(méi)按正常步驟,強(qiáng)制退出了游戲,那就很有可以造成主機(jī)丟失,數(shù)據(jù)沒(méi)來(lái)得及轉(zhuǎn)移給下個(gè)玩家,導(dǎo)致游戲斷線結(jié)束。
同樣,當(dāng)我們Host所在頁(yè)面關(guān)閉時(shí),會(huì)向所有Client發(fā)送一條退出消息。至于誰(shuí)繼承王位,不用關(guān)心,誰(shuí)先得知誰(shuí)做~~ 唯一值得注意的就是:很多瀏覽器不能正常觸發(fā)window.unload事件,這意外著Host可能還沒(méi)來(lái)得把回調(diào)列表移交給他的繼承者就已匆匆離去,于是后人就無(wú)法接管了。為了不讓這種情況出現(xiàn),每當(dāng)新的Host上任,就向所有的Client發(fā)送一個(gè)請(qǐng)求,讓大家把各自關(guān)注的主題重新發(fā)送一遍(之前關(guān)注的都保存著,就為了這個(gè)時(shí)候用)。因此,即使新上任的Host一無(wú)所有,大家也會(huì)把現(xiàn)狀告訴他,可立即投入工作中。
若是強(qiáng)制關(guān)閉了Host所在的頁(yè)面進(jìn)程,那么主機(jī)丟失后一切都將會(huì)掛起。這時(shí)所有Client發(fā)送的數(shù)據(jù)都將有去無(wú)回,只有等到之后出現(xiàn)數(shù)據(jù)發(fā)送失敗,才得知Host已經(jīng)掛了。這時(shí)誰(shuí)先發(fā)現(xiàn)這個(gè)錯(cuò)誤,誰(shuí)就接管Host工作吧。
當(dāng)然,還可以考慮加上心跳機(jī)制,即使Host沒(méi)有掛掉,但其所在進(jìn)程長(zhǎng)時(shí)間占用CPU,導(dǎo)致LocalConnection無(wú)法響應(yīng)消息事件,也可以考慮轉(zhuǎn)移Host了。
由于時(shí)間限制,本例還有不少BUG,以后再慢慢完善。
想看代碼可以瀏覽:http://code.google.com/p/webipc/source/browse/
事實(shí)上純粹的本地通信意義并不大,只有配合遠(yuǎn)程服務(wù)進(jìn)行消息的交互,才更有意義。例如用戶開(kāi)了多個(gè)微博頁(yè)面,傳統(tǒng)的模型必須為每個(gè)頁(yè)面發(fā)起一個(gè)長(zhǎng)連接,來(lái)保持實(shí)時(shí)的數(shù)據(jù)接收。如果使用跨瀏覽器通信,那么只需讓Host發(fā)起一個(gè)連接即可,其余的Client訂閱自己想要的主題,最終只需一個(gè)連接就可以。
相關(guān)文章
JavaScript實(shí)現(xiàn)的反序列化json字符串操作示例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的反序列化json字符串操作,結(jié)合實(shí)例形式分析了eval與JSON.parse兩種反序列化json字符串的相關(guān)操作技巧,需要的朋友可以參考下2018-07-07JS和Canvas實(shí)現(xiàn)圖片的預(yù)覽壓縮和上傳功能
這篇文章主要介紹了JS和Canvas實(shí)現(xiàn)圖片的預(yù)覽壓縮和上傳功能,實(shí)現(xiàn)此功能大概有兩步,第一步用戶選擇需要上傳的圖片,第二步獲取圖片資源壓縮預(yù)覽上傳,具體實(shí)現(xiàn)代碼大家參考下本文2018-03-03微信小程序遍歷Echarts圖表實(shí)現(xiàn)多個(gè)餅圖
這篇文章主要介紹了微信小程序遍歷Echarts圖表實(shí)現(xiàn)多個(gè)餅圖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04js實(shí)現(xiàn)網(wǎng)頁(yè)自動(dòng)刷新可制作節(jié)日倒計(jì)時(shí)效果
這篇文章主要介紹了通過(guò)js實(shí)現(xiàn)的網(wǎng)頁(yè)自動(dòng)刷新,利用此功能可制作節(jié)日倒計(jì)時(shí)效果,需要的朋友可以參考下2014-05-05小程序如何寫(xiě)動(dòng)態(tài)標(biāo)簽的實(shí)現(xiàn)方法
這篇文章主要介紹了小程序如何寫(xiě)動(dòng)態(tài)標(biāo)簽的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02js multiple全選與取消全選實(shí)現(xiàn)代碼
本文章總結(jié)了利用jquery與js實(shí)現(xiàn)multiple全選與取消全選代碼有需要參考的朋友可參考下2012-12-12