html5で複数ページ通信を行うsharedWorkerのコード例
今日、githubで遊んでいて、ログインせずにいくつかのページを閲覧し、あるページでログインした。別のページに切り替えたところ、以下のようなプロンプトが表示されました。
では、これはどのように機能するのでしょうか。一つの方法として考えられるのは、ページがログインしたときにlocalStorageの状態を変更し、他のページは表示されたときに最新の状態を読み、プロンプトを表示して
// The logged-in page
localStorage.setItem('login', true).
// Other pages
document.addEventListener("visibilitychange", function() {
if (localStorage.setItem('login') === 'true') {
alert('You are logged in, please refresh the page');
}
}
しかし、githubではそのようなことはなく、localStorageに該当するフィールドが見つかりませんでした。いろいろ探した結果、sharedWorkerで実装されていることがわかりました。そこで、sharedworkerを見てみます。
sharedWorkerとは
sharedWorker は、その名のとおり、同じオリジンのすべてのページで共有できるタイプのワーカーです。Worker apiと同様に、js urlを渡すことでsharedWorkerのインスタンスを登録することができます。
let myWorker = new SharedWorker('worker.js');
でも、普通の労働者と違って
1 同じjs urlでsharedWorkerを作成するだけで、その後同じurlを使用してsharedWorkerを作成した他のページは、作成されたワーカーを再利用し、そのワーカーはそれらのページで共有されます。
2 sharedWorkerは、ポート経由でメッセージを送受信します。
次に、ワーカーとページの間で具体的にどのようにメッセージが送受信されるかを見ていきます。
メッセージポート
ページで動作するpage.jsと、ワーカーで動作するworker.jsの2つのjsがあるとします。
// page.js
let myWorker = new SharedWorker('worker.js');
// page sends a message through the worker port
myWorker.port.postMessage('hmmm');
// page receives message via worker port
myWorker.port.onmessage = (e) => console.log(e.data);
// worker.js
onconnect= function(e) {
const port = e.ports[0];
port.postMessage('haha');
port.onmessage = (e) => {
console.log(e.data);
}
}
sharedWorkerのデバッグ
上記の例では、ワーカーで console.log を使ってページからのメッセージを出力しましたが、出力されたログはどこで見ることができるでしょうか?ブラウザのアドレスバーに `chrome://inspect' と入力し、サイドバーで shared workers を選択すると、ブラウザで現在実行中のすべてのワーカーを見ることができます。inspect をクリックすると開発者ツールが開き、出力ログを見ることができます。
ここで、ワーカーの名前が untitled であることがわかります。これは、sharedworker コンストラクタが、名前として 2 番目の引数を渡すこともサポートしているからです。
let myWorker = new SharedWorker('worker.js', 'awesome worker');
複数ページ投稿メッセージ
冒頭の例に戻ると、先ほどページとワーカーの通信を実装しましたが、ではワーカーから複数のページにメッセージを送るにはどうすればよいのでしょうか。1つのアイデアとして、ポートをポートプールとしてキャッシュし、すべてのページにメッセージをブロードキャストする必要があるときに、ポートを反復してメッセージを送信することができます: ポートプールには、次のようなものがあります。
// worker js
const portPool = [];
onconnect= function(e) {
const port = e.ports[0];
// Add the port to the portPool at connect time
portPool.push(port);
port.postMessage('haha');
port.onmessage = (e) => {
console.log(e.data);
}
}
function boardcast(message) {
portPool.forEach(port => {
port.portMessage(port);
})
}
これは基本的に、複数のページにメッセージをブロードキャストする機能を提供するものです。
無効なポートを消去する
上記の実装の問題点として、ページを閉じた後にWorkerPool内のポートが自動的にクリアされないため、メモリの無駄遣いになってしまうことが挙げられます。ページが閉じる前に共有ワーカーにページが閉じることを通知し、ワーカーに無効な messagePort を portPool から削除させればよいのです。
// The page
window.onbeforeunload = () => {
myWorker.port.postMessage('TO BE CLOSED');
};
// worker.js
const portPool = [];
onconnect = function(e) {
var port = e.ports[0];
portPool.push(port);
port.onmessage = function(e) {
console.log(e);
if (e.data === 'TO BE CLOSED') {
const index = ports.findIndex(p => p === port);
portPool.splice(index, 1);
}
var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
port.postMessage(workerResult);
}
}
function boardcast(message) {
portPool.forEach(port => {
port.portMessage(port);
})
}
このようにして、簡単な複数ページのブロードキャスト用sharedWorkerを実装し、ちょっとした時間のブロードキャストに利用することができます。
setInterval(() => boardcast(Date.now()), 1000);
参考文献
https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker
https://github.com/mdn/simple-shared-worker
この記事は、html5のsharedWorkerについて、マルチページ通信のサンプルコードを実現するために導入され、より関連するhtml5 sharedWorkerマルチページ通信の内容は、スクリプトホーム以前の記事を検索するか、次の関連記事を閲覧を続けてください、私はあなたが将来的に多くのスクリプトホームをサポートすることを願っています
関連
-
html5 直交ハート型曲線の実装
-
キャンバスを使った移動可能なグリッドの描画方法のサンプルコード
-
モバイルHTML5入力に関するFAQ(要約)
-
HTML5+CSSでfloatを設定しても、真ん中や間違った行の代わりに移動しない問題
-
高解像度画面でのキャンバスブラーの問題を記憶する
-
html5 android compatibility for mobile video (remove play control, full screen)(モバイルビデオ用アンドロイド互換性)。
-
キャンバスを使用して、実装の画像にタイル状の透かしを追加することを教える手
-
HTML5でWeb Notificationのデスクトップ通知を実装する方法
-
キャンバスラバーバンド線引き塗布方法
-
モバイル版Html5におけるBaidu地図のクリックイベント
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
CAPTCHAを生成するHTML5サンプルコード
-
HTML5+ API plusreadyの互換性問題について
-
HTML5 の数値入力コードで整数値のみを受け付けるようにする
-
VSCodeカスタムhtml5テンプレート実装
-
タオバオH5サイン暗号化アルゴリズムの詳細
-
AmazeUIのダウンロード設定とHelloworldの実装について
-
SVG描画をHTMLページに持ってくる実装
-
IOSキーボードがfocusoutイベントでしまわれたときに元の場所に戻らない問題を解決する
-
カスタムお絵かきボード用JavaScript+Canvasサンプルコード
-
HTML5 モバイルポップアップアニメーション効果