TL;DR
Web コンテンツのスクリプトを、バックグラウンドのスレッドで動かすためのブラウザの API。重い処理を UI をブロックせずに実行できる。
なぜ必要か
ブラウザの JavaScript は、通常メインスレッドで動く。メインスレッドで重い処理をすると、その間 UI が反応しなくなる。Web Worker を使えば、重い処理を別のスレッドに逃がせる。
仕組み
Worker は window とは別のグローバルコンテキストで動き、その中では window の代わりに self を使う。fetch() などでネットワークリクエストを送れるほか、WebSocket や IndexedDB も使える。
メインスレッドと Worker は、postMessage() でメッセージを送り、onmessage で受け取る。データは共有されず、構造化複製アルゴリズムでコピーされる。ArrayBuffer のような Transferable オブジェクトは、コピーせずに所有権ごと移せる。
Worker には次の種類がある。
- 専用ワーカー(Dedicated Worker):
new Worker()で作り、作ったスクリプトだけが使える。 - 共有ワーカー(Shared Worker):
new SharedWorker()で作り、複数のウィンドウや iframe からportを通して使える。 - Service Worker: Web アプリ、ブラウザ、ネットワークの間のプロキシとして動き、オフライン対応やプッシュ通知に使う。
例
// main.js
const myWorker = new Worker("worker.js")
myWorker.postMessage([3, 4])
myWorker.onmessage = (e) => {
console.log(`Received: ${e.data}`) // Received: Result: 12
}// worker.js
onmessage = (e) => {
postMessage(`Result: ${e.data[0] * e.data[1]}`)
}注意点
Worker から DOM を直接操作することはできず、window のメソッドやプロパティの多くも使えない。ページを変更したいときは、メインスレッドにメッセージを送り、メインスレッド側で変更する。