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

Notifications API

Notifications API ช่วยให้ PWA ของคุณแสดง system-level notification ได้ ต่างจาก alert box ตรงที่ notification จะปรากฏใน notification tray ของอุปกรณ์และมองเห็นได้แม้ผู้ใช้จะสลับแท็บไปแล้ว

ก่อนแสดง notification ใดๆ คุณต้องขอ permission ก่อน การเรียกนี้จะ return Promise ที่ resolve เป็น "granted", "denied" หรือ "default":

async function askPermission() {
const permission = await Notification.requestPermission();
if (permission === 'granted') {
console.log('Notifications allowed');
} else {
console.warn('Notifications blocked or dismissed');
}
}

เรียกฟังก์ชันนี้เป็นการตอบสนองต่อ user gesture — การคลิกปุ่ม, การส่งฟอร์ม, การ swipe อย่าเรียกตอนโหลดหน้าเพจ

เมื่อได้รับ permission แล้ว คุณสามารถสร้าง notification ได้โดยตรงจาก JavaScript ของหน้าเพจ:

new Notification('Your order shipped!', {
body: 'It will arrive by Thursday.',
icon: '/icons/icon-192.png',
badge: '/icons/badge-72.png',
});

วิธีนี้ใช้ได้ แต่ notification จะไม่ปรากฏถ้าไม่มีแท็บเปิดอยู่ วิธีที่ดีกว่าคือแสดง notification จาก service worker

ใช้ registration.showNotification() บน ServiceWorkerRegistration object โดย SW ยังคงทำงานต่อแม้ทุกแท็บจะปิดแล้ว ดังนั้น notification นี้จึงส่งได้อย่างน่าเชื่อถือ:

// main.js — page code
async function notify(title, options) {
const registration = await navigator.serviceWorker.ready;
registration.showNotification(title, options);
}
notify('Your order shipped!', {
body: 'It will arrive by Thursday.',
icon: '/icons/icon-192.png',
badge: '/icons/badge-72.png',
actions: [
{ action: 'view', title: 'View order' },
{ action: 'dismiss', title: 'Dismiss' },
],
data: { orderId: 'ORD-42' },
});
ตัวเลือกประเภทวัตถุประสงค์
bodystringข้อความรองด้านล่างชื่อเรื่อง
iconstring (URL)รูปภาพขนาดใหญ่ข้าง notification
badgestring (URL)icon ขาวดำขนาดเล็กสำหรับ status bar
imagestring (URL)รูปภาพ inline ขนาดใหญ่
actionsarrayปุ่มที่ผู้ใช้สามารถกดได้โดยไม่ต้องเปิดแอป
dataanyข้อมูลส่วนตัวที่ส่งไปยัง notificationclick handler
tagstringแทนที่ notification ที่มีอยู่ที่มี tag เดียวกัน
renotifybooleanแจ้งเตือนผู้ใช้อีกครั้งแม้จะแทนที่ notification ที่มี tag แล้ว
requireInteractionbooleanทำให้ notification ยังคงมองเห็นได้จนกว่าผู้ใช้จะโต้ตอบ
silentbooleanปิดเสียงและการสั่น

event notificationclick จะเกิดขึ้นใน service worker เมื่อผู้ใช้แตะ notification หรือปุ่ม action:

// sw.js — service worker
self.addEventListener('notificationclick', (event) => {
event.notification.close();
if (event.action === 'view') {
// Open or focus the app
event.waitUntil(
clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
if (clientList.length > 0) {
return clientList[0].focus();
}
return clients.openWindow('/orders/' + event.notification.data.orderId);
})
);
}
});

อย่าลืมเรียก event.notification.close() เสมอ — บน Android notification จะยังคงเปิดอยู่จนกว่าจะปิดอย่างชัดเจน

demo ด้านล่างแสดง local notification จาก service worker กด “Grant permission” เมื่อได้รับการแจ้ง จากนั้นกด “Notify me”

Runs a real service worker + manifest in your browser.
ตัวเลือกBenefitCost
ขอ permission แบบ contextual (หลัง user engage แล้ว)permission grant rate สูงกว่า ผู้ใช้เข้าใจเหตุผลก่อนตัดสินใจต้องออกแบบ trigger point ที่เหมาะสม เพิ่มงานออกแบบ UX
ขอ permission ทันทีตอนโหลดหน้าแรกเขียนโค้ดง่ายที่สุดpermission block rate สูงมาก ผู้ใช้กด deny เพราะยังไม่เห็นคุณค่าของแอป
  • ขอ Notification permission ทันทีตอนหน้าเว็บโหลด ทำให้ผู้ใช้ส่วนใหญ่กด block ก่อนจะรู้ด้วยซ้ำว่าแอปทำอะไร
  • ไม่ handle กรณี permission ถูก “denied” ถาวร ทำให้โค้ดพยายามขอซ้ำไปเรื่อยๆ โดยไม่มีทาง recover
  • แสดง notification โดยไม่ใส่ icon/tag ที่เหมาะสม ทำให้ notification เดียวกันซ้อนกันหลายอันแทนที่จะ replace อันเดิม

💡 ตัวอย่างจากของจริง

Facebook — ขอ permission เฉพาะหลังผู้ใช้ทำ action ที่เกี่ยวข้อง (เช่นส่งข้อความ) แทนที่จะขอตั้งแต่แรกเข้า

สายการบินต่างๆ — ใช้ Notifications API แจ้งเตือนเวลา check-in โดยขอ permission ตอนผู้ใช้กำลังจองตั๋วที่เป็นจังหวะที่สมเหตุสมผลที่สุด

Notification.requestPermission() return อะไร?
ทำไมจึงนิยมใช้ registration.showNotification() มากกว่า new Notification()?
event notificationclick ทำงานที่ไหน?
notification option ใดที่แทนที่ notification เดิมที่มี identifier เดียวกัน?