ใช้ Service Worker เพื่อจัดการการแจ้งเตือน

Kate Jeffreys
Kate Jeffreys

ใน Codelab นี้ คุณจะได้ใช้ Service Worker เพื่อจัดการการแจ้งเตือน คำสั่งที่นี่ถือว่าคุณคุ้นเคยกับ Service Worker และพื้นฐานของการขอสิทธิ์การแจ้งเตือนและการส่งการแจ้งเตือนอยู่แล้ว หากต้องการทบทวนเรื่องการแจ้งเตือน โปรดดู Codelab เริ่มต้นใช้งาน Notifications API ดูข้อมูลเพิ่มเติมเกี่ยวกับ Service Worker ได้ที่ข้อมูลเบื้องต้นเกี่ยวกับ Service Worker ของ Matt Gaunt

ทำความคุ้นเคยกับแอปตัวอย่างและโค้ดเริ่มต้น

เริ่มต้นด้วยการดูแอปที่ใช้งานจริงในแท็บ Chrome ใหม่

  1. กด `Control+Shift+J` (หรือ `Command+Option+J` ใน Mac) เพื่อเปิด DevTools
  2. คลิกแท็บคอนโซล

  3. ตรวจสอบว่าได้เลือกตัวเลือกข้อมูลในเมนูแบบเลื่อนลงระดับ ข้างช่องตัวกรอง

  4. ในคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บของแอปที่ใช้งานจริง คุณควรเห็นข้อความคอนโซลต่อไปนี้

    TODO: Implement getRegistration()

    นี่คือข้อความจากฟังก์ชัน Stub ที่คุณจะใช้ใน Codelab นี้

ตอนนี้มาดูโค้ดของแอปตัวอย่างกัน

  1. ดูข้อมูลใน public/index.js

    • โดยมี Stub 4 รายการสำหรับฟังก์ชันที่คุณจะใช้ ได้แก่ registerServiceWorker, getRegistration, unRegisterServiceWorker และ sendNotification

    • ฟังก์ชัน requestPermission จะขอสิทธิ์จากผู้ใช้เพื่อส่งการแจ้งเตือน หากคุณทำ Codelab เริ่มต้นใช้งาน Notifications API คุณจะเห็นว่ามีการใช้ฟังก์ชัน requestPermission ที่นี่ ความแตกต่างเพียงอย่างเดียวคือตอนนี้ฟังก์ชันนี้จะอัปเดตอินเทอร์เฟซผู้ใช้หลังจากแก้ไขคำขอสิทธิ์ด้วย

    • ฟังก์ชัน updateUI จะรีเฟรชปุ่มและข้อความทั้งหมดของแอป

    • initializePage ฟังก์ชันจะตรวจหาความสามารถของ Service Worker ในเบราว์เซอร์และอัปเดตอินเทอร์เฟซผู้ใช้ของแอป

    • สคริปต์จะรอจนกว่าหน้าเว็บจะโหลดเสร็จ แล้วจึงเริ่มต้น

  2. เปิด public/service-worker.js

    ตามชื่อที่แนะนำ คุณจะต้องเพิ่มโค้ดลงในแอปเพื่อลงทะเบียนไฟล์นี้เป็น Service Worker

    แม้ว่าแอปจะยังไม่ได้ใช้ไฟล์ แต่ไฟล์ก็มีโค้ดเริ่มต้นบางส่วนที่จะพิมพ์ข้อความไปยังคอนโซลเมื่อเปิดใช้งาน Service Worker

    คุณจะเพิ่มโค้ดลงใน public/service-worker.js เพื่อจัดการการแจ้งเตือนเมื่อ Service Worker ได้รับ

ลงทะเบียน Service Worker

ในขั้นตอนนี้ คุณจะเขียนโค้ดที่ทำงาน เมื่อผู้ใช้คลิกลงทะเบียน Service Worker ใน UI ของแอป โค้ดนี้จะลงทะเบียน public/service-worker.js เป็น Service Worker

  1. เปิด public/index.js แทนที่ฟังก์ชัน registerServiceWorker ด้วยโค้ดต่อไปนี้

    // Use the Service Worker API to register a service worker.
    async function registerServiceWorker() {
      await navigator.serviceWorker.register('./service-worker.js')
      updateUI();
    }
    

    โปรดทราบว่า registerServiceWorker ใช้การประกาศ async function เพื่อให้การจัดการ Promise สะดวกยิ่งขึ้น ซึ่งช่วยให้คุณawaitค่าที่แก้ไขแล้วของPromiseได้ เช่น ฟังก์ชันด้านบนจะรอผลลัพธ์ของการลงทะเบียน Service Worker ก่อนที่จะอัปเดต UI ดูข้อมูลเพิ่มเติมได้ที่ await ใน MDN

  2. ตอนนี้ผู้ใช้ลงทะเบียน Service Worker ได้แล้ว คุณจึงรับข้อมูลอ้างอิงไปยังออบเจ็กต์การลงทะเบียน Service Worker ได้ ใน public/index.js ให้แทนที่ฟังก์ชัน getRegistration ด้วยโค้ดต่อไปนี้

    // Get the current service worker registration.
    function getRegistration() {
      return navigator.serviceWorker.getRegistration();
    }
    

    ฟังก์ชันด้านบนใช้ Service Worker API เพื่อรับการลงทะเบียน Service Worker ปัจจุบัน หากมี ซึ่งจะช่วยให้การอ้างอิงการลงทะเบียน Service Worker สะดวกยิ่งขึ้น

  • หากต้องการทำให้ฟังก์ชันการลงทะเบียน Service Worker เสร็จสมบูรณ์ ให้เพิ่มโค้ดเพื่อยกเลิกการลงทะเบียน Service Worker แทนที่ฟังก์ชัน unRegisterServiceWorker ด้วยโค้ดต่อไปนี้

    // Unregister a service worker, then update the UI.
    async function unRegisterServiceWorker() {
      // Get a reference to the service worker registration.
      let registration = await getRegistration();
      // Await the outcome of the unregistration attempt
      // so that the UI update is not superceded by a
      // returning Promise.
      await registration.unregister();
      updateUI();
    }
    

ในแท็บที่คุณกำลังดูแอปเวอร์ชันที่ใช้งานจริง ให้โหลดหน้าเว็บซ้ำ ตอนนี้ปุ่มลงทะเบียน Service Worker และยกเลิกการลงทะเบียน Service Worker ควรใช้งานได้แล้ว

ส่งการแจ้งเตือนไปยัง Service Worker

ในขั้นตอนนี้ คุณจะเขียนโค้ดที่จะทำงานเมื่อผู้ใช้คลิกส่งการแจ้งเตือนใน UI ของแอป โค้ดนี้จะสร้างการแจ้งเตือน ตรวจสอบว่ามีการลงทะเบียน Service Worker แล้ว จากนั้นส่งการแจ้งเตือนไปยัง Service Worker โดยใช้วิธี postMessage

เปิด public/index.js และ แทนที่ฟังก์ชัน sendNotification ด้วยโค้ดต่อไปนี้

// Create and send a test notification to the service worker.
async function sendNotification() {
  // Use a random number as part of the notification data
  // (so you can tell the notifications apart during testing!)
  let randy = Math.floor(Math.random() * 100);
  let notification = {
    title: 'Test ' + randy,
    options: { body: 'Test body ' + randy }
  };
  // Get a reference to the service worker registration.
  let registration = await getRegistration();
  // Check that the service worker registration exists.
  if (registration) {
    // Check that a service worker controller exists before
    // trying to access the postMessage method.
    if (navigator.serviceWorker.controller) {
      navigator.serviceWorker.controller.postMessage(notification);
    } else {
      console.log('No service worker controller found. Try a soft reload.');
    }
  }
}

โค้ดดังกล่าวทำสิ่งต่อไปนี้

  • sendNotification เป็นฟังก์ชันแบบอะซิงโครนัส คุณจึงใช้ await เพื่อรับการอ้างอิงการลงทะเบียน Service Worker ได้

  • เมธอด postMessage ของ Service Worker จะส่งข้อมูลจากแอปไปยัง Service Worker ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบ MDN เกี่ยวกับ postMessage

  • โค้ดจะตรวจสอบว่ามีพร็อพเพอร์ตี้ navigator.serviceWorker.controller หรือไม่ก่อนที่จะพยายามเข้าถึงฟังก์ชัน postMessage navigator.serviceWorker.controller จะเป็น null หากไม่มี Service Worker ที่ใช้งานอยู่ หรือหากมีการรีเฟรชหน้าเว็บโดยบังคับ (Shift+โหลดซ้ำ) ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบเกี่ยวกับตัวควบคุม ServiceWorker ใน MDN

จัดการการแจ้งเตือนใน Service Worker

ในขั้นตอนนี้ คุณจะเขียนโค้ดใน Service Worker ที่จะจัดการข้อความที่โพสต์ไปยัง Service Worker และแสดงการแจ้งเตือนต่อผู้ใช้

เปิด public/service-worker.js เพิ่มโค้ดต่อไปนี้ที่ส่วนท้ายของไฟล์

// Show notification when received
self.addEventListener('message', (event) => {
  let notification = event.data;
  self.registration.showNotification(
    notification.title,
    notification.options
  ).catch((error) => {
    console.log(error);
  });
});

คำอธิบายโดยย่อมีดังนี้

  • self คือการอ้างอิงถึง Service Worker เอง

  • แม้ว่าตอนนี้ Service Worker จะจัดการการแสดงการแจ้งเตือน แต่ UI ของแอปหลักยังคงมีหน้าที่รับสิทธิ์การแจ้งเตือนจากผู้ใช้ หากไม่ได้รับสิทธิ์ สัญญาที่ showNotification ส่งคืนจะถูกปฏิเสธ โค้ดด้านบนใช้บล็อก catch เพื่อหลีกเลี่ยงข้อผิดพลาดในการปฏิเสธ Promise ที่ไม่ได้แคช และจัดการข้อผิดพลาดนี้อย่างราบรื่นยิ่งขึ้น

ไปที่ Codelab ถัดไปในชุดนี้: สร้างเซิร์ฟเวอร์การแจ้งเตือนแบบพุช