שימוש ב-Service Worker לניהול התראות

Kate Jeffreys
Kate Jeffreys

ב-codelab הזה תשתמשו ב-service worker כדי לנהל התראות. ההוראות כאן מניחות שאתם כבר מכירים את מופעי Service Worker ואת הבסיס של בקשת הרשאה לשליחת התראות ושליחת התראות. אם אתם צריכים לרענן את הידע שלכם בנושא התראות, כדאי לעיין ב-codelab בנושא תחילת העבודה עם Notifications API. מידע נוסף על קובצי שירות (service worker) זמין במאמר Introduction to service workers (מבוא לקובצי שירות) של מאט גאנט.

היכרות עם האפליקציה לדוגמה ועם קוד ההתחלה

מתחילים בצפייה באפליקציה הפעילה בכרטיסייה החדשה ב-Chrome:

  1. מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את כלי הפיתוח.
  2. לוחצים על הכרטיסייה מסוף.

  3. מוודאים שהאפשרות מידע נבחרה בתפריט הנפתח רמות לצד התיבה מסנן.

  4. במסוף DevTools של האפליקציה הפעילה, אמורה להופיע הודעת מסוף:

    TODO: Implement getRegistration().

    זוהי הודעה מ-stub של פונקציה שתטמיעו ב-codelab הזה.

עכשיו נסתכל על הקוד של האפליקציה לדוגמה.

  1. כדאי להציץ בסרטון הזה public/index.js:

    • יש ארבעה stub לפונקציות שתטמיעו: 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)

בשלב הזה, תכתבו קוד שיופעל כשהמשתמש ילחץ על Register service worker בממשק המשתמש של האפליקציה. הקוד הזה ירשום את 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 כדי לטפל בהבטחות בצורה נוחה יותר. כך תוכלו await את הערך שנפתר של Promise. לדוגמה, הפונקציה שלמעלה ממתינה לתוצאה של רישום service worker לפני שהיא מעדכנת את ממשק המשתמש. מידע נוסף זמין במאמר 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), מוסיפים קוד לביטול הרישום של קובץ השירות. מחליפים את הפונקציה 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();
    }
    

בכרטיסייה שבה צופים באפליקציה הפעילה, טוענים מחדש את הדף. הכפתורים Register service worker (רישום קובץ שירות) ו-Unregister service worker (ביטול הרישום של קובץ שירות) אמורים לפעול עכשיו.

שליחת התראות ל-service worker

בשלב הזה, תכתבו קוד שיפעל כשהמשתמש ילחץ על שליחת התראה בממשק המשתמש של האפליקציה. הקוד הזה ייצור התראה, יבדוק אם רשום 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 אם אין קובץ שירות פעיל, או אם הדף רוענן בכוח (Shift+טעינה מחדש). מידע נוסף זמין במסמכי התיעוד של ServiceWorker controller ב-MDN.

טיפול בהתראות ב-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 מטפל בהצגת ההתראות, ממשק המשתמש הראשי של האפליקציה עדיין אחראי לקבלת הרשאת ההתראות מהמשתמש. אם ההרשאה לא ניתנת, ההבטחה שמוחזרת על ידי showNotification נדחית. הקוד שלמעלה משתמש בבלוק catch כדי למנוע שגיאת דחייה Promise שלא נתפסה, ולטפל בשגיאה הזו בצורה קצת יותר חלקה.

כדאי לעבור אל ה-codelab הבא בסדרה הזו: יצירת שרת של התראות פוש.