Web Locks API
(developer.mozilla.org)- Web Locks API ช่วยให้แท็บเดียวหรือเว็บเวิร์กเกอร์สามารถขอรับล็อกแบบอะซิงโครนัส ทำงาน แล้วปล่อยล็อกได้
- ระหว่างที่ล็อกถูกถืออยู่ สคริปต์อื่นภายใน origin เดียวกันจะไม่สามารถรับล็อกเดียวกันได้ จึงช่วยประสานการใช้ทรัพยากรระหว่างหลายแท็บหรือเวิร์กเกอร์ได้อย่างปลอดภัย
- ใช้งานได้เฉพาะใน Secure Context(HTTPS) และใช้งานได้ใน Web Workers
แนวคิดหลักและวิธีใช้งาน
- ล็อก(Lock) คือทรัพยากรเชิงนามธรรมที่ระบุด้วยชื่อซึ่งกำหนดโดยเว็บแอปพลิเคชัน
- ตัวอย่างเช่น เมื่อต้องซิงก์ IndexedDB และเครือข่ายจากหลายแท็บ สามารถใช้ล็อกชื่อ “my_net_db_sync” เพื่อให้มีเพียงแท็บเดียวที่ซิงก์ได้ในแต่ละครั้ง
- ลำดับการใช้งาน:
- ขอรับล็อก
- ทำงานแบบอะซิงโครนัส
- เมื่อทำงานเสร็จจะปล่อยล็อกโดยอัตโนมัติ
ตัวอย่างโค้ด
navigator.locks.request("my_resource", async (lock) => {
await do_something();
await do_something_else();
});
- ระหว่างที่ล็อกถูกถืออยู่ คำขออื่นสำหรับล็อกเดียวกันจะถูกเพิ่มเข้าไปในคิว และเมื่อปล่อยล็อกแล้ว คำขอแรกจะถูกประมวลผล
ตัวเลือก
- mode: โหมดเริ่มต้นคือ “exclusive” (เฉพาะผู้ใช้เดียว) และสามารถใช้โหมด “shared” (ใช้ร่วมกัน) ได้ด้วย โดย “exclusive” อนุญาตได้เพียงหนึ่งคำขอ ส่วน “shared” อนุญาตได้หลายคำขอ
- ifAvailable: หากไม่สามารถรับล็อกได้ทันที คำขอจะล้มเหลว และ callback จะคืนค่า null
- steal: ปลดล็อกเดิมที่มีชื่อเดียวกันและให้สิทธิ์คำขอใหม่ก่อน
- signal: สามารถยกเลิกคำขอผ่าน AbortSignal ได้ (เช่น ใช้ทำ timeout)
การมอนิเตอร์
- สามารถใช้ navigator.locks.query() เพื่อตรวจสอบสถานะล็อกของ origin ปัจจุบันได้
- มีประโยชน์สำหรับการดีบัก และตรวจสอบได้ว่าล็อกใดกำลังถูกถืออยู่ รวมถึงมีการขอล็อกใดบ้าง
การใช้งานขั้นสูง
- หากต้องการควบคุมจังหวะสิ้นสุดของงานอะซิงโครนัสอย่างชัดเจน สามารถคืนค่า Promise ได้
let resolve;
const p = new Promise((res) => { resolve = res });
navigator.locks.request("my_resource", (lock) => p);
- เมื่อเรียก resolve() ล็อกจะถูกปล่อย
การป้องกันเดดล็อก(Deadlock)
- เดดล็อกคือสถานการณ์ที่คำขอต่าง ๆ ชนกันเพราะลำดับการทำงาน ทำให้ไม่สามารถดำเนินต่อได้
- ตัวอย่างเช่น หากแท็บ 1 ถือครองล็อก A และแท็บ 2 ถือครองล็อก B จากนั้นแท็บ 1 ขอล็อก B และแท็บ 2 ขอล็อก A ทั้งสองฝ่ายจะต้องรอกันเอง
- เพื่อป้องกันปัญหานี้:
- ไม่ควรซ้อนคำขอรับล็อก
- ควรรักษาลำดับของการขอรับล็อกให้สม่ำเสมอ
- ตั้งค่า timeout เพื่อยกเลิกคำขอ
อินเทอร์เฟซ
- Lock: ให้ชื่อและโหมดของล็อกที่ร้องขอ
- LockManager: มีเมธอดสำหรับขอล็อกใหม่หรือตรวจสอบล็อกที่มีอยู่
- สามารถรับอินสแตนซ์ได้ผ่าน navigator.locks
- WorkerNavigator.locks ใช้งานได้ใน Web Workers
สเปกและการรองรับของเบราว์เซอร์
- สเปก: Web Locks API
- ความเข้ากันได้กับเบราว์เซอร์: รองรับเฉพาะบางเบราว์เซอร์ และสามารถตรวจสอบการรองรับในเบราว์เซอร์ล่าสุดได้ที่ MDN
ความเห็นของ GN⁺
- Web Locks API มีประโยชน์ในการแก้ปัญหาการซิงก์ทรัพยากรในสภาพแวดล้อมแบบอะซิงโครนัส
- เนื่องจากมีโอกาสเกิดเดดล็อกได้ จึงต้องใช้อย่างระมัดระวัง และควรพิจารณามาตรการป้องกัน เช่น การตั้งค่า timeout
- Shared mode สามารถช่วยเพิ่มประสิทธิภาพในงานแบบอ่านอย่างเดียวได้ แต่ก็ยังต้องพิจารณาเรื่อง race condition อย่างรอบคอบ
- API นี้สามารถใช้เป็นทางเลือกเพื่อแก้ปัญหาการซิงก์ของ localStorage หรือ IndexedDB ที่มีอยู่เดิมได้
ยังไม่มีความคิดเห็น