• Web Locks API ช่วยให้แท็บเดียวหรือเว็บเวิร์กเกอร์สามารถขอรับล็อกแบบอะซิงโครนัส ทำงาน แล้วปล่อยล็อกได้
  • ระหว่างที่ล็อกถูกถืออยู่ สคริปต์อื่นภายใน origin เดียวกันจะไม่สามารถรับล็อกเดียวกันได้ จึงช่วยประสานการใช้ทรัพยากรระหว่างหลายแท็บหรือเวิร์กเกอร์ได้อย่างปลอดภัย
  • ใช้งานได้เฉพาะใน Secure Context(HTTPS) และใช้งานได้ใน Web Workers

แนวคิดหลักและวิธีใช้งาน

  • ล็อก(Lock) คือทรัพยากรเชิงนามธรรมที่ระบุด้วยชื่อซึ่งกำหนดโดยเว็บแอปพลิเคชัน
  • ตัวอย่างเช่น เมื่อต้องซิงก์ IndexedDB และเครือข่ายจากหลายแท็บ สามารถใช้ล็อกชื่อ “my_net_db_sync” เพื่อให้มีเพียงแท็บเดียวที่ซิงก์ได้ในแต่ละครั้ง
  • ลำดับการใช้งาน:
    1. ขอรับล็อก
    2. ทำงานแบบอะซิงโครนัส
    3. เมื่อทำงานเสร็จจะปล่อยล็อกโดยอัตโนมัติ

ตัวอย่างโค้ด

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 ที่มีอยู่เดิมได้

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น