33

共有ワーカーを使用して、Web アプリケーションのすべてのウィンドウ/タブのリストを維持しようとしています。したがって、次のコードが使用されます。

//lives in shared-worker.js
var connections=[];//this represents the list of all windows/tabs
onconnect=function(e){
  connections.push(e.ports[0]);
};

ウィンドウが作成されるたびにshared-worker.jsワーカーとの接続が確立され、ワー​​カーはウィンドウとの接続をconnectionsリストに追加します。

ユーザーがウィンドウを閉じると、共有ワーカーとの接続が期限切れになるため、connections変数から削除する必要があります。しかし、それを行うための信頼できる方法が見つかりません。

仕様を見ると、変数のオブジェクトはconnections、接続がまだ有効かどうかを確認するためのプロパティ/関数を保持していないようです。

出来ますか?
繰り返しますが、全体的な目標は、すべてのウィンドウ/タブのリストを取得することです。

編集:アプローチは、共有ワーカー メッセージをウィンドウにして、返信を期待することです。共有ワーカーが応答を受信しない場合、ウィンドウが閉じていると見なされます。私の実験では、このアプローチは信頼できるものではありませんでした。問題は、ウィンドウが閉じられているのか、返信に時間がかかっているのかを判断する方法がないことです。

4

4 に答える 4

13

私は一週間中、同じ問題を回避するためにドキュメントに深く関わってきました。

問題は MessagePort の仕様です。悪いニュースは、エラー処理がなく、閉じられたかどうかを判断するためのフラグ、メソッド、またはイベントがないことです。

良いニュースは、実行可能なソリューションを作成したことですが、それは多くのコードです。

サポートしているブラウザ間でも、アクティビティの処理が異なることに注意してください。たとえば、閉じたポートにメッセージを送信したり閉じたりしようとすると、Opera はエラーをスローします。悪いニュースは、try-catch を使用してエラーを処理する必要があることです。良いニュースは、そのフィードバックを使用して、少なくとも一方のポートを閉じることができることです。

Chrome と Safari は警告なしに失敗し、フィードバックがなく、無効なオブジェクトを終了する方法がありません。


私の解決策には、配信確認またはカスタムの「コールバック」アプローチが含まれます。setTimeout を使用し、その ID をコマンドで SharedWorker に渡します。コマンドを処理する前に、タイムアウトをキャンセルするための確認が返されます。そのタイムアウトは通常、closeConnection() メソッドにフックされます。

これは、プリエンプティブではなくリアクティブなアプローチをとっています。もともと私は TCP/IP プロトコル モデルを使用して遊んでいましたが、各プロセスを処理するためにより多くの関数を作成する必要がありました。


例としていくつかの疑似コード:

クライアント/タブ コード:

function customClose() {
    try {
        worker.port.close();
    } catch (err) { /* For Opera */ }
}
function send() {
    try {
        worker.port.postMessage({command: "doSomething", content: "some Data", id: setTimeout(function() { customClose(); ); }, 1000);
    } catch (err) { /* For Opera */ }
}

スレッド/ワーカー コード:

function respond(p, d) {
    p.postMessage({ command: "confirmation", id: d.id });
}
function message(e) {// Attached to all ports onmessage
    if (e.data.id) respond(this, e.data);
    if (e.data.command) e.data.command(p, e.data);// Execute command if it exists passing context and content
}

ここに完全なデモを配置しました: http://www.cdelorme.com/SharedWorker/

私はスタック オーバーフローに慣れていないので、スタック オーバーフローが大きなコード ポストを処理する方法に慣れていませんが、私の完全な解決策は 2 つの 150 行のファイルです。


送達確認だけでは完璧ではないので、コンポーネントを追加して改善に取り組みました。

特に、ChatBox システムでこれを調査していたので、EventSource (SSE)、XHR、および WebSocket を使用したかったのですが、おそらく SharedWorker オブジェクト内でサポートされているのは XHR のみであり、SharedWorker にすべてのサーバーを実行させたい場合は制限が生じますコミュニケーション。

さらに、SharedWorker をサポートしていないブラウザーで動作する必要があるため、SharedWorker 内で長時間の重複処理を作成することになり、あまり意味がありません。

結局、SharedWorker を実装すると、開いているタブのみの通信チャネルとして使用され、1 つのタブが Control タブになります。

コントロール タブが閉じられている場合、SharedWorker は認識しないため、SharedWorker に setInterval を追加して、開いているすべてのポートに数秒ごとに空の応答要求を送信します。これにより、Chrome と Safari は、メッセージが処理されていないときに閉じられた接続を排除し、コントロール タブを変更できるようになります。

ただし、これはまた、SharedWorker プロセスが終了した場合、タブが同じアプローチを使用して SharedWorker にチェックインする間隔が必要であることも意味します。同じコードを使用する他のブラウザ。


したがって、配信確認のためのコールバックの組み合わせを見ることができるように、接続の知識を維持するために、setTimeout と setInterval を両端から使用する必要があります。それはできますが、それは後部の巨大な痛みです.

于 2012-12-03T07:11:23.030 に答える
1

PortCollection便利ですが、どのブラウザーにも実装されていないようです。

これは MessagePort オブジェクトの不透明な配列として機能するため、スクリプトが MessagePort オブジェクトを反復処理できるようにしながら、関連性がなくなったときにオブジェクトをガベージ コレクションできます。

ソース; http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#portcollection

編集; Chrome の問題が発生しました。http://crbug.com/263356

于 2012-12-01T18:36:16.323 に答える