ข้ามไปยังเนื้อหา

Cross-Tab & Files

แอปพลิเคชันเว็บสมัยใหม่มักทำงานในหลายแท็บพร้อมกัน เมื่อแท็บหนึ่งอัปเดตข้อมูล แท็บอื่นจะรู้ได้อย่างไร? เมื่อแอปต้องเขียนไฟล์ขนาดใหญ่จะหลีกเลี่ยงการเขียนทับงานของแท็บอื่นได้อย่างไร? โมดูลนี้จะตอบคำถามทั้งสองข้อ

browser มี API สี่ตัวที่ทำงานร่วมกัน:

  • BroadcastChannel — รับ-ส่งข้อความแบบ publish/subscribe ระหว่างทุกแท็บ (และ worker) บน origin เดียวกัน
  • storage event — เกิดขึ้นในแท็บอื่นเมื่อมีการเขียน localStorage; กลไกการแจ้งเตือนดั้งเดิมก่อน BroadcastChannel
  • Web Locks — primitive สำหรับ mutual-exclusion ที่ทำให้การเข้าถึง resource ทำงานเป็น serial ป้องกัน race condition
  • File System Access / OPFS — อ่านและเขียนไฟล์จริง (หรือ sandbox ส่วนตัวของ origin) ด้วย API แบบ async
flowchart LR
  subgraph Origin["Same origin (scheme + host + port)"]
    TabA["Tab A\n(writer)"] -->|postMessage| BC["BroadcastChannel\n'app-updates'"]
    BC -->|onmessage| TabB["Tab B\n(listener)"]
    BC -->|onmessage| TabC["Tab C\n(listener)"]
    TabA -->|setItem| LS[(localStorage)]
    LS -->|storage event| TabB
    LS -->|storage event| TabC
  end
BroadcastChannel และ storage event ส่งข้อความไปยังทุกแท็บอื่นบน origin เดียวกัน
บทเรียนสิ่งที่จะเรียนรู้
หน้านี้API ทั้งสี่สำหรับ cross-tab และไฟล์ และเวลาที่ควรใช้แต่ละตัว
broadcastchannelnew BroadcastChannel(name), postMessage, onmessage, close; เทียบกับ storage event
web-locksnavigator.locks.request, โหมด exclusive กับ shared, ifAvailable, locks.query()
cross-tab-stateรวม BroadcastChannel + localStorage/IndexedDB สำหรับ shared state; leader election ด้วย Web Locks
file-system-access-opfsshowOpenFilePicker / showSaveFilePicker (ต้องใช้ gesture) และ OPFS navigator.storage.getDirectory()
APIการส่งข้อมูลต้อง gestureทำงานใน workersเก็บถาวร
BroadcastChannelแท็บอื่นไม่ใช่ไม่
storage eventแท็บอื่นไม่ไม่ไม่
Web Locksแท็บเดียวกันไม่ใช่ไม่
File System Accessใช่ (picker)ไม่ใช่
OPFSไม่ใช่ใช่

โค้ดด้านล่างสร้าง BroadcastChannel แล้ว post และรับข้อความในหน้าเดียวกัน ในแอปจริง sender และ receiver อยู่คนละแท็บ

Browser Storage
API ใดส่งข้อความไปยังทุกแท็บอื่นบน origin เดียวกัน โดยไม่ต้องใช้ user gesture?
`storage` event เกิดขึ้นเมื่อ localStorage ถูกเขียน แท็บใดจะได้รับ event นี้?
API ใดต้องใช้ user gesture (เช่น คลิกปุ่ม) ก่อนจึงจะแสดง file picker ได้?