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)單演示,本例使用了基于廣播的觀察者模式:每個(gè)終端可以訂閱自己感興趣的主題,也可以向廣播發(fā)送消息,通知其他感興趣的終端。
Demo: http://www.etherdream.com/FunnyScript/WebIPC/ (多開幾個(gè)瀏覽器頁(yè)面小窗口,即可測(cè)試)
比較遺憾的是最新版的Chrome瀏覽器仍然無(wú)法和其他瀏覽器進(jìn)程交互:(
如果沒有錯(cuò)誤發(fā)生,應(yīng)該就是如下的效果:

在任何一個(gè)頁(yè)面上的操作,都會(huì)立即同步到其他頁(yè)面里,只要Observe了感興趣的主題。
為什么要使用觀察者模式呢?因?yàn)榭邕M(jìn)程的通信是比較耗資源的,所以不感興趣的消息可以直接不訂閱,而不是收到再放棄。
LocalConnection是為單一的通信設(shè)計(jì)的,雖然使用很簡(jiǎn)單,但可用的接口少之又少。想直接用它來(lái)廣播事件,或者消息路由,門都沒有。
因此底層的消息發(fā)送上沒有太多可選余地,只能簡(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)程間通信,并沒有第三方服務(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è)沒用被占用的作為管道名。Host回調(diào)時(shí)只需send(channel+id)就能通知對(duì)應(yīng)的Client。
然而,這個(gè)Host服務(wù)僅僅是假象的。我們根本沒法在頁(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,以此類推。。。

由于沒有第三方服務(wù)器,每個(gè)Client都可以兼職做Host。到這里,你是不是想到了局域網(wǎng)游戲?由于沒有服務(wù)器,第一個(gè)創(chuàng)建的玩家便是主機(jī)。當(dāng)他退出時(shí),主機(jī)就交給了第二個(gè)玩家。如果他沒按正常步驟,強(qiáng)制退出了游戲,那就很有可以造成主機(jī)丟失,數(shù)據(jù)沒來(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可能還沒來(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沒有掛掉,但其所在進(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)行消息的交互,才更有意義。例如用戶開了多個(gè)微博頁(yè)面,傳統(tǒng)的模型必須為每個(gè)頁(yè)面發(fā)起一個(gè)長(zhǎng)連接,來(lái)保持實(shí)時(shí)的數(shù)據(jù)接收。如果使用跨瀏覽器通信,那么只需讓Host發(fā)起一個(gè)連接即可,其余的Client訂閱自己想要的主題,最終只需一個(gè)連接就可以。
相關(guān)文章
js return返回多個(gè)值,通過(guò)對(duì)象的屬性訪問(wèn)方法
下面小編就為大家?guī)?lái)一篇js return返回多個(gè)值,通過(guò)對(duì)象的屬性訪問(wèn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
JavaScript中的標(biāo)簽語(yǔ)句用法分析
這篇文章主要介紹了JavaScript中的標(biāo)簽語(yǔ)句用法,實(shí)例分析了標(biāo)簽語(yǔ)句的功能、定義及相關(guān)使用技巧,需要的朋友可以參考下2015-02-02
Javascript遞歸打印Document層次關(guān)系實(shí)例分析
這篇文章主要介紹了Javascript遞歸打印Document層次關(guān)系的方法,實(shí)例分析了javascript中Document的層次關(guān)系,需要的朋友可以參考下2015-05-05
微信小程序如何獲知用戶運(yùn)行小程序的場(chǎng)景教程
這篇文章主要給大家介紹了在微信小程序中如何獲知用戶運(yùn)行小程序場(chǎng)景的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)跟著小編一起來(lái)看看吧。2017-05-05
在IE中調(diào)用javascript打開Excel的代碼(downmoon原作)
在IE中調(diào)用javascript打開Excel的代碼(downmoon原作)...2007-04-04
alert中斷settimeout計(jì)時(shí)功能
在測(cè)試過(guò)程中發(fā)現(xiàn)alert會(huì)中斷settimeout的計(jì)時(shí)功能,關(guān)閉對(duì)話框后,settimeout的時(shí)間會(huì)重頭開始計(jì)時(shí),而不是從中斷處,感興趣的朋友可以了解下2013-07-07
js浮點(diǎn)數(shù)保留兩位小數(shù)點(diǎn)示例代碼(四舍五入)
本篇文章主要介紹了js浮點(diǎn)數(shù)保留兩位小數(shù)點(diǎn)示例代碼(四舍五入) 需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-12-12

