Shared Worker を試す

前回は、Dedicated Worker を触ってみましたが、引き続き WebWorker を触っていきます。
今回は、Shared Worker です。

参考

試す

環境準備

前回に引き続き環境の準備は、vite で準備します。

1
2
3
4
npm init @vitejs/app app --template vanilla
cd app
npm install
npm run dev

このタイミングで、main.js は main.ts に変更。
index.html での参照先も main.ts に変えておきます。

Shared Worker 作る

main.ts で Worker として作成するソースコードを URL で指定します。

main.ts
1
const myWorker = new SharedWorker("worker.ts");
worker.ts
1
2
3
4
5
const _worker: SharedWorkerGlobalScope = self as any;

_worker.onconnect = async (event: MessageEvent) => {
console.log(event);
};

SharedWorker は、Dedicated Worker と異なり、onconnectの実装が必要だそう。

そして SharedWorker でのconsole.logは、通常の開発者コンソールに出て来ませんでした。
調べてみると、chrome://inspect/#workers にアクセスして inspect を押すと、別画面で開発者コンソールが開きます。
こちらに console.log の内容が出力されていました。

main スレッド(UI スレッド) <= Worker スレッド 方向の通信

続けて、main スレッド(UI スレッド) <= Worker スレッド 方向の通信を試します。

main.ts
1
2
3
4
const myWorker = new SharedWorker("worker.ts");

// SharedWorker は、myWorker.postMessage ではなく myWorker.port.postMessage
myWorker.port.postMessage([1, 2, 3]);
worker.ts
1
2
3
4
5
6
7
8
9
const _worker: SharedWorkerGlobalScope = self as any;

_worker.onconnect = async (event: MessageEvent) => {
const port = event.ports[0];

port.onmessage = async (event: MessageEvent) => {
console.log(event.data);
};
};

これを実行すると、Worker 側のコンソールで以下のように表示されます。

1
(3) [1, 2, 3]

複数のタブで、同じページを開くと複数 (3) [1, 2, 3] が出てきます。
Chrome の場合、別のウィンドウでも開くと、 (3) [1, 2, 3] が出てきますが、ユーザーをゲストにしたら表示されませんでした。
境界点が「ユーザー」のようです。

main スレッド(UI スレッド) => Worker スレッド方向の通信

逆方向の Worker から、main スレッドの通信は以下の通り。

main.ts
1
2
3
4
5
6
7
8
const myWorker = new SharedWorker("worker.ts");

myWorker.port.postMessage([1, 2, 3]);

// worker からのメッセージの受付も portオブジェクトを介して
myWorker.port.onmessage = (event: MessageEvent) => {
console.log(event.data);
};
worker.ts
1
2
3
4
5
6
7
8
9
const _worker: SharedWorkerGlobalScope = self as any;

_worker.onconnect = async (event: MessageEvent) => {
const port = event.ports[0];

port.onmessage = async (mEvent: MessageEvent) => {
port.postMessage(mEvent.data);
};
};

実行すると、ページ側の開発者コンソールで (3) [1, 2, 3] 側の表示が確認できました。

SharedWorker のエラーを拾う

onerror の定義ができるかと思ったがどうもうまくいかない様子。
調べても、明確に記述が見つけられず。

Vite で SharedWorker

Dedicated Worker の時と同様に、vite では、SharedWorker の import に対応していました。
次の通りです。

main.ts
1
2
3
4
5
6
7
8
9
10
// ?sharedworker ?sharedworker&inline も可
import SharedWorker from "./worker?sharedworker";

const myWorker = new SharedWorker();

myWorker.port.postMessage([1, 2, 3]);

myWorker.port.onmessage = (event: MessageEvent) => {
console.log(event.data);
};

ちょっと不思議な現象?

複数タブで SharedWorker の確認をしていた時、動きのおかしくなった瞬間があった。
chrome://inspect/#workers で、terminate を押して停止。
再度ページ開き直したら、最新のコードで Worker が動き出した。


今回は SharedWorker を触ってみました。
引き続き、WebWorker 関連の確認を進めていきます。

ではでは。