SharedWorker
SharedWorker คืออะไร?
หัวข้อที่มีชื่อว่า “SharedWorker คืออะไร?”SharedWorker คือ Web Worker ที่ถูกแชร์ร่วมกันใน browsing context ทั้งหมด (tabs, windows, iframes) ที่มีต้นกำเนิดเดียวกัน ต่างจาก Dedicated Worker ที่มีอยู่เพียงสำหรับหน้าเดียว SharedWorker จะมีชีวิตอยู่จนกว่า tab ที่เชื่อมต่ออยู่ทั้งหมดจะปิด ให้คิดว่าเป็น “บริการ” น้ำหนักเบาภายใน browser — สามารถเก็บ state ที่แชร์ร่วมกัน ลดคำขอเครือข่ายที่ซ้ำกัน และซิงโครไนซ์ข้อมูลข้าม tab โดยไม่ต้องพึ่ง backend
ความแตกต่างหลักจาก Dedicated Worker
หัวข้อที่มีชื่อว่า “ความแตกต่างหลักจาก Dedicated Worker”| Dedicated Worker | SharedWorker | |
|---|---|---|
| Instance ต่อ tab? | ใช่ — หนึ่งต่อหน้า | ไม่ — หนึ่งแชร์ร่วมกันทุก tab |
| Constructor | new Worker(url) | new SharedWorker(url) |
| การสื่อสาร | worker.postMessage โดยตรง | worker.port.postMessage ผ่าน MessagePort |
| Worker รับ connect หรือไม่? | ไม่ | ใช่ — event onconnect จะยิงทุกครั้งที่มี tab ใหม่ |
| อายุการใช้งาน | ผูกกับหน้าที่เป็นเจ้าของ | จนกว่า tab ที่เชื่อมต่อทั้งหมดจะปิด |
มีขั้นตอนสำคัญสี่ขั้นตอนในการใช้งาน SharedWorker
ขั้นตอนที่ 1 — ในเธรดหลัก:
const worker = new SharedWorker('shared-worker.js');worker.port.start(); // must call start() to activate the portworker.port.postMessage('hello');worker.port.onmessage = (e) => console.log(e.data);ขั้นตอนที่ 2 — ใน worker (shared-worker.js):
const ports = [];self.onconnect = (e) => { const port = e.ports[0]; ports.push(port); port.start(); port.onmessage = (ev) => { // echo to all connected tabs for (const p of ports) p.postMessage('echo: ' + ev.data); };};ทำไม SharedWorker จึงต้องใช้หลาย tab
หัวข้อที่มีชื่อว่า “ทำไม SharedWorker จึงต้องใช้หลาย tab”พลังที่แท้จริงของ SharedWorker อยู่ที่การแชร์ state ข้าม tab การเปิด tab เดียวแทบไม่แสดงให้เห็นความสามารถนี้ — คุณต้องมีอย่างน้อยสอง tab จึงจะเห็นความแตกต่าง นั่นคือเหตุผลที่ตัวอย่างที่รันได้ด้านล่างเปิดใน StackBlitz ซึ่งคุณสามารถเปิดสองหน้าต่าง browser ที่ชี้ไปยัง URL เดียวกันได้
ตัวอย่างที่รันได้: ตัวนับแชร์ร่วมกันข้าม tab (StackBlitz)
หัวข้อที่มีชื่อว่า “ตัวอย่างที่รันได้: ตัวนับแชร์ร่วมกันข้าม tab (StackBlitz)”Needs multiple tabs / a SharedWorker context — open in StackBlitz to run.
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
SharedWorker (instance เดียวทุก tab) | ประหยัด memory, แชร์ state และ coordination ข้าม tab ได้ทันที (เช่น connection เดียวสำหรับหลาย tab) | Debug ยากกว่า — DevTools ต้องเปิดแยกสำหรับ shared worker, และ historically iOS Safari ไม่รองรับหรือรองรับไม่สมบูรณ์ |
| Dedicated Worker (instance ต่อ tab) | รองรับ browser ครบทุกตัว, debug ง่ายเพราะผูกกับหน้าเดียว | ใช้ memory มากขึ้นเมื่อเปิดหลาย tab พร้อมกัน ไม่มี state ที่แชร์ร่วมกันในตัว |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- พึ่งพา
SharedWorkerบน iOS Safari โดยไม่มี fallback — support ของSharedWorkerบน iOS Safari ไม่แน่นอนในอดีต ควร feature-detect ด้วยtypeof SharedWorker !== 'undefined'แล้ว fallback ไปใช้ Dedicated Worker หรือกลไกอื่น - ลืมเรียก
port.start()— ทั้งฝั่งหน้าเว็บและฝั่ง worker ต้องเรียกport.start()ก่อน message ถึงจะไหลผ่าน MessagePort ไม่อย่างนั้น message จะถูก queue ค้างไว้เฉยๆ - คาดว่า
onconnectจะยิงแค่ครั้งเดียว —onconnectยิงทุกครั้งที่มี tab ใหม่มาเชื่อมต่อ ต้อง push port ใหม่เข้า list ที่มีอยู่แทนที่จะ overwrite ไม่งั้น tab เก่าจะหลุดจากการสื่อสาร
💡 ตัวอย่างจากของจริง
Slack — ใช้
SharedWorkerเพื่อรักษา WebSocket connection เดียวที่แชร์ร่วมกันทุก tab ที่เปิดอยู่ ลดจำนวน connection ไปยัง server และซิงค์สถานะ real-time ข้าม tab ได้ทันทีระบบแดชบอร์ดหรือเครื่องมือ back-office ที่เปิดหลาย tab พร้อมกัน — ใช้
SharedWorkerแชร์ token การยืนยันตัวตนและแคช API response เดียวกันข้าม tab เพื่อลดจำนวนคำขอไปยัง server