私は一週間中、同じ問題を回避するためにドキュメントに深く関わってきました。
問題は 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 を両端から使用する必要があります。それはできますが、それは後部の巨大な痛みです.