אירועי דחיפה

עד עכשיו, דיברנו על הרשמה של משתמש ושליחת הודעת דחיפה. השלב הבא הוא לקבל את הודעת ה-Push במכשיר של המשתמש ולהציג התראה (וכן כל עבודה אחרת שאנחנו רוצים לבצע).

אירוע הדחיפה

כשמתקבלת הודעה, היא מובילה לשליחת אירוע דחיפה ל-Service Worker.

הקוד להגדרה של האזנה לאירוע דחיפה צריך להיות דומה למדי לכל מאזינים אחרים של אירועים שצריך לכתוב ב-JavaScript:

self.addEventListener('push', function(event) {
    if (event.data) {
    console.log('This push event has data: ', event.data.text());
    } else {
    console.log('This push event has no data.');
    }
});

החלק המוזר ביותר בקוד הזה לרוב המפתחים שהם חדשים ב-Service Workers הוא המשתנה self. בדרך כלל משתמשים ב-self ב-Web Workers, שהם Service worker. self מתייחס להיקף הגלובלי, כמו window בדף אינטרנט. אבל לגבי עובדי אינטרנט ו-service worker, self מתייחס ל-worker עצמו.

בדוגמה שלמעלה, אפשר לחשוב על self.addEventListener() כהוספה של event listener ל-Service Worker עצמו.

בדוגמה של אירוע הדחיפה, אנחנו בודקים אם יש נתונים ומדפיסים משהו במסוף.

יש דרכים אחרות לנתח נתונים מאירוע דחיפה:

// Returns string
event.data.text()

// Parses data as JSON string and returns an Object
event.data.json()

// Returns blob of data
event.data.blob()

// Returns an arrayBuffer
event.data.arrayBuffer()

רוב האנשים משתמשים ב-json() או ב-text() בהתאם למה שהם מצפים לקבל מהאפליקציה.

הדוגמה הזו ממחישה איך להוסיף Push event listener ואיך לגשת לנתונים, אבל חסרות בו שני רכיבי פונקציונליות חשובים מאוד. לא מוצגת התראה ולא נעשה שימוש ב-event.waitUntil().

אני רוצה לחכות

אחד הדברים שצריך להבין לגבי Service Workers הוא שאין לכם שליטה מועטה על הזמן שבו קוד של Service Worker יפעל. הדפדפן מחליט מתי להוציא אותו ממצב שינה ומתי לסגור אותו. הדרך היחידה לומר לדפדפן "היי, אני עסוק מאוד עושה דברים חשובים", היא להעביר הבטחה ל-method של event.waitUntil(). כך הדפדפן ימשיך לפעול ב-Service Worker עד שתוסדר ההבטחה שהעברתם.

באירועי דחיפה, יש דרישה נוספת להציג התראה לפני ההבטחה שהעברתם.

דוגמה בסיסית להצגת התראה:

self.addEventListener('push', function(event) {
    const promiseChain = self.registration.showNotification('Hello, World.');

    event.waitUntil(promiseChain);
});

קריאה ל-self.registration.showNotification() היא השיטה שבה מוצגת התראה למשתמש ומחזירה הבטחה שתסתיים אחרי הצגת ההתראה.

כדי שהדוגמה הזו תהיה ברורה ככל האפשר, הקציתי את ההבטחה למשתנה שנקרא promiseChain. לאחר מכן, המזהה מועבר אל event.waitUntil(). ברור לי שהנושא הזה ארוך מאוד, אבל נתקלתי בכמה בעיות שהגיעו לשיא כתוצאה מהבנה שגויה של מה שצריך להעביר אל waitUntil() או כתוצאה משרשראות הבטחה שבורות.

דוגמה מורכבת יותר עם בקשת נתונים ברשת ומעקב אחר אירוע הדחיפה באמצעות ניתוח נתונים יכולה להיראות כך:

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        return self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

כאן אנחנו מפעילים פונקציה שמחזירה הבטחה pushReceivedTracking(), ולצורך הדוגמה, אנחנו יכולים להתחזות לבקשת רשת לספק ניתוח הנתונים שלנו. בנוסף, אנחנו שולחים בקשת רשת, מקבלים את התגובה ומציגים התראה באמצעות נתוני התגובות לכותרת ולהודעה של ההתראה.

כדי להבטיח שה-Service Worker יישאר בחיים בזמן ששתי המשימות האלה מבוצעות, על ידי שילוב ההבטחות האלה עם Promise.all(). ההבטחה שתתקבל מועברת אל event.waitUntil(), כלומר הדפדפן ימתין עד ששתי ההבטחות יסתיימו לפני שהוא יבדוק שתוצג התראה ויסגור את Service Worker.

יש סיבה לדאוג לגבי waitUntil() ואיך להשתמש בו, כי אחת הבעיות הנפוצות ביותר שאיתם מתמודדים מפתחים היא ששרשרת ההבטחה לא נכונה או לא תקינה, Chrome יציג את הודעת ברירת המחדל הזו:

תמונה של הודעת ברירת המחדל ב-Chrome

רק ב-Chrome תוצג ההתראה 'האתר הזה עודכן ברקע' כשמתקבלת הודעת Push ובאירוע הדחיפה ב-Service Worker לא מוצגת התראה אחרי שההבטחה שהועברה ל-event.waitUntil() הסתיימה.

הסיבה העיקרית שמפתחים נחשפים לכך היא שהקוד שלהם בדרך כלל יתקשר ל-self.registration.showNotification(), אבל הם לא עושים שום דבר עם ההבטחה שהוא מחזיר. כתוצאה מכך, לסירוגין, תוצג הודעת ברירת המחדל. לדוגמה, אנחנו יכולים להסיר את ההחזר על self.registration.showNotification() בדוגמה שלמעלה, ואנחנו מסתכנים לראות את ההתראה הזו.

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

כך אפשר לפספס בקלות.

חשוב לזכור: אם ההתראה הזו מופיעה, עליך לבדוק את שרשראות ההבטחה ואת event.waitUntil().

בחלק הבא נסביר מה אפשר לעשות כדי לעצב התראות ואיזה תוכן נוכל להציג.

השלבים הבאים

שיעורי Lab