Cookie Store API
ปัญหาของ document.cookie
หัวข้อที่มีชื่อว่า “ปัญหาของ document.cookie”document.cookie เป็น synchronous API ที่ออกแบบในช่วงกลางทศวรรษ 1990 มีจุดที่น่าหงุดหงิดสามอย่าง:
- ต้อง parse เอง — การอ่าน cookie ตามชื่อต้องแยก string และวนลูป
- การเขียนใช้ string — ต้องสร้าง cookie string ด้วยตัวเอง
- ไม่มี change event — ไม่มีวิธีสังเกตเมื่อแท็บอื่นหรือ server เปลี่ยน cookie
Cookie Store API แก้ปัญหาทั้งสามด้วย interface ที่สะอาดแบบ Promise-based
การรองรับของ browser
หัวข้อที่มีชื่อว่า “การรองรับของ browser”Cookie Store API มีใน Chrome และ Edge (browser ที่ใช้ Chromium) แต่ Firefox ยังไม่รองรับ ควรตรวจสอบการรองรับก่อนใช้เสมอ
cookieStore.get — อ่าน cookie ชิ้นเดียว
หัวข้อที่มีชื่อว่า “cookieStore.get — อ่าน cookie ชิ้นเดียว”คืน Promise ที่ resolve เป็น object CookieListItem หรือ null ถ้า cookie ไม่มีอยู่:
const cookie = await cookieStore.get('theme');if (cookie) { console.log(cookie.name); // 'theme' console.log(cookie.value); // 'dark'}object ที่คืนยังมี property domain, path, expires, secure, sameSite, และ httpOnly ด้วย
cookieStore.set — เขียน cookie
หัวข้อที่มีชื่อว่า “cookieStore.set — เขียน cookie”รับคู่ name/value เป็น string หรือ object options:
// รูปแบบสั้นawait cookieStore.set('theme', 'dark');
// รูปแบบ options — แนะนำสำหรับควบคุม attributeawait cookieStore.set({ name: 'theme', value: 'dark', maxAge: 86400, sameSite: 'lax',});คืน Promise ที่ resolve เมื่อ cookie ถูกเขียนแล้ว
cookieStore.delete — ลบ cookie
หัวข้อที่มีชื่อว่า “cookieStore.delete — ลบ cookie”await cookieStore.delete('theme');คืน Promise ที่ resolve เมื่อ cookie ถูกลบ เทียบเท่ากับการตั้ง Max-Age=0
cookieStore.getAll — อ่าน cookie ทั้งหมด
หัวข้อที่มีชื่อว่า “cookieStore.getAll — อ่าน cookie ทั้งหมด”const allCookies = await cookieStore.getAll();allCookies.forEach(c => console.log(c.name, c.value));ต่างจาก document.cookie ตรงที่คืน array ของ object จริงๆ — ไม่ต้อง parse string
Change event
หัวข้อที่มีชื่อว่า “Change event”Cookie Store API ช่วยให้ฟัง cookie change แบบ reactive ได้:
cookieStore.addEventListener('change', event => { event.changed.forEach(c => { console.log('Cookie changed:', c.name, '=', c.value); }); event.deleted.forEach(c => { console.log('Cookie deleted:', c.name); });});event.changed เป็น array ของ cookie ที่ถูกตั้งค่าหรืออัปเดต event.deleted เป็น array ของ cookie ที่ถูกลบ ทำงานข้ามแท็บสำหรับ cookie ที่ไม่ได้จำกัดขอบเขตไว้ที่แท็บเดียว
รูปแบบ feature-detect
หัวข้อที่มีชื่อว่า “รูปแบบ feature-detect”เนื่องจากการรองรับ browser ยังไม่ครบ ควร feature-detect และ fallback ไปใช้ document.cookie เสมอ:
async function getTheme() { if ('cookieStore' in window) { const c = await cookieStore.get('theme'); return c ? c.value : null; } else { // fallback document.cookie var pairs = document.cookie.split('; '); for (var i = 0; i < pairs.length; i++) { var p = pairs[i].split('='); if (p[0] === 'theme') return decodeURIComponent(p[1]); } return null; }}Demo ที่รันได้: cookieStore พร้อม fallback
หัวข้อที่มีชื่อว่า “Demo ที่รันได้: cookieStore พร้อม fallback”ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Cookie Store API | โค้ดสั้นและอ่านง่ายกว่ามาก — await cookieStore.get() แทนการ split string เอง แถมมี change event ให้ฟังแบบ reactive | Firefox ยังไม่รองรับ ต้อง feature-detect และเขียน fallback ไปใช้ document.cookie เสมอ เพิ่มโค้ดสองชุดสำหรับ logic เดียวกัน |
document.cookie | รองรับทุก browser ไม่ต้องมี fallback | เป็น synchronous string API ต้อง parse เองทุกครั้ง ไม่มี change event ในตัว |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- เรียก
cookieStore.get()/.set()โดยไม่ feature-detect ก่อน — โค้ดจะพังทันทีบน Firefox เพราะcookieStoreไม่มีอยู่ในwindow - ลืมว่า method ของ Cookie Store API เป็น async ทั้งหมด — เขียนโค้ดราวกับว่าค่าคืนกลับมาแบบ synchronous แล้วได้ Promise object แทนค่าจริง ต้อง
awaitเสมอ - คาดหวังว่า
changeevent จะทำงานเหมือนกันทุก browser และทุกสถานการณ์ — พฤติกรรมข้ามแท็บของ event นี้ยังไม่ได้มาตรฐานเดียวกันในทุก implementation ควรทดสอบจริงก่อนพึ่งพาเป็น core logic
💡 ตัวอย่างจากของจริง
แอปที่ sync ค่า theme/preference ข้ามแท็บ — ใช้
cookieStore.addEventListener('change', ...)เพื่ออัปเดต UI ทันทีเมื่อผู้ใช้เปลี่ยนค่าในแท็บอื่น โดยไม่ต้อง poll หรือ reloadProgressive enhancement บนเว็บ production — ทีมที่ต้องรองรับทั้ง Chrome/Edge และ Firefox มักเขียน wrapper function ที่ feature-detect
cookieStoreแล้ว fallback ไปdocument.cookieเพื่อให้โค้ด business logic เขียนครั้งเดียวใช้ได้ทุก browser