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

Kate Jeffreys
Kate Jeffreys

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

ระบบจะบล็อกการแจ้งเตือนจากแอป Glitch ที่ฝังไว้โดยอัตโนมัติ คุณจึงไม่สามารถดูตัวอย่างแอปในหน้านี้ได้ แต่ให้ทำดังนี้

  1. คลิกรีมิกซ์เพื่อแก้ไขเพื่อให้โปรเจ็กต์แก้ไขได้
  2. หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ เต็มหน้าจอ

เนื้อหาที่ขัดข้องควรเปิดในแท็บ Chrome ใหม่

ขณะทำ Codelab นี้ ให้ทำการเปลี่ยนแปลงโค้ดใน Glitch ที่ฝังอยู่ในหน้านี้ รีเฟรชแท็บใหม่ที่มีแอปเวอร์ชันที่เผยแพร่อยู่เพื่อดูการเปลี่ยนแปลง

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

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

  1. กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
  2. คลิกแท็บคอนโซล

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

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

    TODO: Implement getRegistration()

    นี่คือข้อความจากสแต็บฟังก์ชันที่คุณจะใช้ในโค้ดแล็บนี้

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

  1. ใน Glitch ที่ฝัง ให้ดูที่ public/index.js

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

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

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

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

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

  2. เปิด public/service-worker.js ใน Glitch ที่ฝัง

    ตามชื่อที่บอกไว้ คุณจะต้องเพิ่มโค้ดลงในแอปเพื่อลงทะเบียนไฟล์นี้เป็น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 ในเครื่องมือแก้ไข Glitch ที่ฝังอยู่ แทนที่ฟังก์ชัน 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 เพื่อให้การจัดการสัญญาสะดวกขึ้น ซึ่งจะช่วยให้คุณ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

ในเครื่องมือแก้ไข Glitch ที่ฝังอยู่ ให้เปิด 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 ที่จะจัดการข้อความที่โพสต์มาและแสดงการแจ้งเตือนต่อผู้ใช้

เปิด public/service-worker.js ในเครื่องมือแก้ไข Glitch ที่ฝังอยู่ เพิ่มโค้ดต่อไปนี้ที่ส่วนท้ายของไฟล์

// 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 ที่ไม่ได้จับ และจัดการข้อผิดพลาดนี้อย่างมีประสิทธิภาพมากขึ้น

หากติดขัด ให้ดูโค้ดที่สมบูรณ์ได้ที่ glitch.com/edit/#!/codelab-notifications-service-worker-completed

ไปที่ Codelab ถัดไปในชุดนี้: สร้างเซิร์ฟเวอร์ Push Notification