ホームページ >ウェブフロントエンド >jsチュートリアル >Webクロスブラウザプロセス通信(Webクロスドメイン)_JavaScriptスキル
在之前一篇文章里尝试了跨浏览器的数据共享,最后提到使用LocalConnection还可以实现跨浏览器消息交互的可行性。
花了两个晚上简略的研究了下,LocalConnection的单向通信非常的简单,不过要实现多个终端交互,必须自己实现一套消息机制,见智见仁了。
为了简单演示,本例使用了基于广播的观察者模式:每个终端可以订阅自己感兴趣的主题,也可以向广播发送消息,通知其他感兴趣的终端。
Demo: http://www.etherdream.com/FunnyScript/WebIPC/ (多开几个浏览器页面小窗口,即可测试)
比较遗憾的是最新版的Chrome浏览器仍然无法和其他浏览器进程交互:(
如果没有错误发生,应该就是如下的效果:
在任何一个页面上的操作,都会立即同步到其他页面里,只要Observe了感兴趣的主题。
为什么要使用观察者模式呢?因为跨进程的通信是比较耗资源的,所以不感兴趣的消息可以直接不订阅,而不是收到再放弃。
LocalConnection是为单一的通信设计的,虽然使用很简单,但可用的接口少之又少。想直接用它来广播事件,或者消息路由,门都没有。
因此底层的消息发送上没有太多可选余地,只能简单的点对点发送。我们必须创建多个LocalConnection,来实现消息的汇聚和分发。
LocalConnection真正能用的只有两个方法:
connect(name) —— 创建管道(每个LocalConnection只能创建一个管道,每个管道名只能有一个)
send(name, ...) —— 向管道发送数据
如果只有两个终端通信,那么一切都是那么简单。。。
只需简单的将消息发送给对方即可。
不过有多个终端情况就大不相同了。由于我们是本地进程间通信,并没有第三方服务器主持,加上LocalConnection只能点对点的发送消息。意味着每次广播都要给其他所有的终端都发送一次,这样复杂度就大大增加了。
为了简化结构,我们模拟一个LocalConnection作为Host,在第一次启动时运行。其余的作为Client,每次广播消息都提交给Host,由它来调度。
Host维护着一个回调列表。当Client对某个主题(subject)感兴趣时,可以发送<主题ID,自己的管道名>给Host来订阅。于是Host就把此Client的管道名添加到该主题的回调列表里。以后若有该主题的消息,即可根据回调列表通知订阅的Client。
为了能让Host和Client通信更简单,这里使用channel+ID的命名规则,来创建管道名。
Host的ID为空,于是Client发送数据只需send(channel)即可;
Client的ID从1~100,选一个没用被占用的作为管道名。Host回调时只需send(channel+id)就能通知对应的Client。
然而,这个Host服务仅仅是假象的。我们根本没法在页面之外运行一个第三方服务,一切只能在页面中实现!于是我们把第一次启动的页面作为Host。当这个页面关闭时,我们再通知第二个页面创建Host,以此类推。。。
由于没有第三方服务器,每个Client都可以兼职做Host。到这里,你是不是想到了局域网游戏?由于没有服务器,第一个创建的玩家便是主机。当他退出时,主机就交给了第二个玩家。如果他没按正常步骤,强制退出了游戏,那就很有可以造成主机丢失,数据没来得及转移给下个玩家,导致游戏断线结束。
同様に、ホストが配置されているページが閉じられると、終了メッセージがすべてのクライアントに送信されます。誰が王位を継承するかについては、心配しないでください。最初に知った人がそれをします~~ 唯一注目に値するのは、多くのブラウザが window.unload イベントを正常にトリガーできないということです。これは、予想外にホストに時間がない可能性があることを意味します。後継者へのコールバックリストをめぐって彼は急いで去ったため、将来の世代が引き継ぐことができませんでした。 この状況の発生を防ぐために、新しいホストが就任するたびに、すべてのクライアントにリクエストが送信され、関心のあるトピックを再送信するよう求められます (以前のトピックはすべて保存されますが、今回のみです) )。したがって、新しいホストが何も持っていなくても、皆が彼に現状を伝え、すぐに仕事に取り掛かることができます。
ホストが存在するページプロセスが強制的に閉じられると、ホストが失われた後、すべてがハングします。現時点では、クライアントによって送信されたすべてのデータが返されることはありません。後でデータ送信が失敗した場合にのみ、ホストがハングアップしたことがわかります。現時点では、このエラーを最初に発見した人がホストの作業を引き継ぎます。
もちろん、ホストがハングアップしないにもかかわらず、そのプロセスが長時間 CPU を占有し、LocalConnection がメッセージ イベントに応答できなくなる場合でも、ハートビート メカニズムの追加を検討することもできます。ホストを転送します。
時間の制約により、この例にはまだ多くのバグがありますが、将来的には徐々に改善される予定です。
コードを確認したい場合は、次の場所を参照してください: http://code.google.com/p/webipc/source/browse/
実際、純粋なローカル通信にはあまり意味がありません。リモート サービスと連携してメッセージをやり取りすることのみに意味があります。たとえば、ユーザーが複数の Weibo ページを開いた場合、従来のモデルでは、リアルタイムのデータ受信を維持するためにページごとに長い接続を開始する必要があります。クロスブラウザ通信を使用する場合、ホストに接続を開始させるだけでよく、他のクライアントは必要なトピックをサブスクライブできるため、最終的に必要な接続は 1 つだけです。