בשנת 2015 השקנו את הסנכרון ברקע, שמאפשר ל-service worker לדחות את העבודה עד שהמשתמש יקבל חיבור. המשמעות היא שהמשתמש יכול להקליד הודעה, ללחוץ על 'שליחה' ולהשאיר את האתר בידיעה שההודעה תישלח עכשיו, או כשיהיה לו קישוריות.
זו תכונה שימושית, אבל כדי שה-Service Worker יהיה פעיל במהלך השליפה. זו לא בעיה בקטעים קצרים של עבודה, כמו שליחת הודעה, אבל אם המשימה נמשכת יותר מדי זמן, הדפדפן ימות על השירות, אחרת זה עלול לסכן את הפרטיות והסוללה של המשתמש.
מה קורה אם צריך להוריד משהו שעשוי להימשך זמן רב, כמו סרט, פודקאסטים או רמות של משחק? לשם כך משמש אחזור ברקע.
האחזור ברקע זמין כברירת מחדל החל מגרסה 74 של Chrome.
הנה הדגמה מהירה של שתי דקות שמראה את המצב הרגיל לעומת השימוש ב'אחזור ברקע':
כדאי לנסות את הדמו בעצמכם ולעיין בקוד.
איך זה עובד
כך פועל אחזור ברקע:
- אתם אומרים לדפדפן לבצע קבוצה של אחזור נתונים ברקע.
- הדפדפן מאחזר את הפריטים האלה ומציג את ההתקדמות למשתמש.
- אחרי שהאחזור יושלם או נכשל, הדפדפן יפתח את Service Worker ויפעיל אירוע כדי לספר לכם מה קרה. כאן אתם מחליטים מה לעשות עם התשובות, אם בכלל.
אם המשתמש סוגר דפים באתר אחרי שלב 1, זה בסדר, ההורדה תמשיך. מכיוון שהאחזור גלוי מאוד וקל לבטל אותו, אין חשש לפרטיות מפני משימה של סנכרון ברקע שנמשכת יותר מדי זמן. מכיוון ש-service worker לא פועל כל הזמן, אין חשש שהוא עלול לנצל לרעה את המערכת, למשל לבצע כריית ביטקוין ברקע.
בפלטפורמות מסוימות (כמו Android), יכול להיות שהדפדפן יסגר אחרי שלב 1, כי הדפדפן יכול להעביר את האחזור למערכת ההפעלה.
אם המשתמש מתחיל את ההורדה במצב אופליין או עובר למצב אופליין במהלך ההורדה, האחזור ברקע יושהה ויחודש מאוחר יותר.
ה-API
זיהוי תכונות
כמו בכל תכונה חדשה, חשוב לבדוק אם הדפדפן תומך בה. כדי להשתמש באחזור ברקע, פשוט:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
התחלת אחזור ברקע
ה-API הראשי תלוי ברישום של קובץ שירות (service worker), לכן חשוב לוודא שרשמת קודם קובץ שירות. לאחר מכן:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.fetch('my-fetch', ['/ep-5.mp3', 'ep-5-artwork.jpg'], {
title: 'Episode 5: Interesting things.',
icons: [{
sizes: '300x300',
src: '/ep-5-icon.png',
type: 'image/png',
}],
downloadTotal: 60 * 1024 * 1024,
});
});
backgroundFetch.fetch
מקבלת שלושה ארגומנטים:
פרמטרים | |
---|---|
id |
string הוא המזהה הייחודי של אחזור הרקע הזה.
|
requests |
Array<Request|string>
הדברים שרוצים לאחזר. מחרוזות יטופלו ככתובות URL ויהפכו ל- Request דרך new Request(theString) .
אפשר לאחזר דברים ממקורות אחרים, כל עוד המשאבים מאפשרים זאת, דרך CORS. הערה: בשלב הזה, דפדפן Chrome לא תומך בבקשות שדורשות בדיקת קדם של CORS. |
options |
אובייקט שעשוי לכלול את הפרטים הבאים: |
options.title |
string כותרת שתוצג בדפדפן לצד ההתקדמות. |
options.icons |
Array<IconDefinition> מערך של אובייקטים עם 'src', 'size' ו-'type'. |
options.downloadTotal |
number הגודל הכולל של גופי התגובה (לאחר הסרת ה-gzip). הוספת הלוגו היא אופציונלית, אבל מומלץ מאוד לספק אותו. הוא משמש כדי להודיע למשתמש על גודל ההורדה ולספק מידע על ההתקדמות. אם לא תספקו את המידע הזה, הדפדפן יאמר למשתמש שהגודל לא ידוע, וכתוצאה מכך יש סיכוי גבוה יותר שהמשתמש יפסיק את ההורדה. אם מספר ההורדות ברקע חורג מהמספר שצוין כאן, הוא יבוטל. זה בסדר גמור אם ההורדה קטנה מ- |
הפונקציה backgroundFetch.fetch
מחזירה הבטחה שמתקבלת בה BackgroundFetchRegistration
. אדבר על הפרטים בהמשך. ההבטחה נדחית אם המשתמש ביטל את ההסכמה להורדות, או אם אחד מהפרמטרים שסופקו לא תקין.
שליחת הרבה בקשות לאחזור אחד ברקע מאפשרת לשלב דברים שהם מבחינה לוגית דבר אחד מבחינת המשתמש. לדוגמה, אפשר לחלק את הסרט לאלפי משאבים (בדרך כלל עם MPEG-DASH) ולהוסיף לו משאבים נוספים כמו תמונות. רמה של משחק יכולה להתפרס על פני משאבים רבים של JavaScript, של תמונות ושל אודיו. אבל למשתמש, זה פשוט 'הסרט' או 'השלב'.
אחזור של אחזור קיים ברקע
אפשר לקבל אחזור קיים ברקע כמו:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
...על ידי העברת ה-id של אחזור הרקע הרצוי. הפונקציה get
מחזירה את הערך undefined
אם אין אחזור פעיל ברקע עם המזהה הזה.
אחזור ברקע נחשב 'פעיל' מרגע הרישום שלו, עד שהוא מסתיים בהצלחה, נכשל או מבוטל.
אפשר לקבל רשימה של כל האחזורים הפעילים ברקע באמצעות getIds
:
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
הרשמות לאחזור ברקע
ל-BackgroundFetchRegistration
(bgFetch
בדוגמאות שלמעלה) יש את הפרטים הבאים:
מאפיינים | |
---|---|
id |
string המזהה של אחזור הרקע. |
uploadTotal |
number מספר הבייטים שיישלחו לשרת. |
uploaded |
number מספר הבייטים שנשלחו בהצלחה. |
downloadTotal |
number הערך שצוין כשנרשמת האחזור ברקע, או אפס. |
downloaded |
number מספר הבייטים שהתקבלו בהצלחה. הערך הזה עשוי לרדת. לדוגמה, אם החיבור יתנתק ולא ניתן יהיה להמשיך את ההורדה, הדפדפן יתחיל מחדש את אחזור המשאב הזה מאפס. |
result |
אחד מהבאים:
|
failureReason |
אחד מהבאים:
|
recordsAvailable |
boolean האם יש גישה לבקשות או לתשובות הבסיסיות? אחרי שהערך הזה יהיה שגוי, לא ניתן יהיה להשתמש ב- |
שיטות | |
abort() |
מחזירה Promise<boolean> ביטול האחזור ברקע. ההבטחה שמוחזרת מופיעה עם ערך True אם האחזור בוטל בהצלחה. |
matchAll(request, opts) |
הפונקציה מחזירה את הערך Promise<Array<BackgroundFetchRecord>> Get the requests and responses. הארגומנטים כאן זהים לארגומנטים של API המטמון. קריאה ללא ארגומנטים מחזירה הבטחה לכל הרשומות. המידע על הסיבות האפשריות מפורט כאן. |
match(request, opts) |
הפונקציה מחזירה את הערך Promise<BackgroundFetchRecord> כמו למעלה, אבל מתייחסת להתאמה הראשונה. |
אירועים | |
progress |
הפעלה כשאחד מהפרמטרים uploaded , downloaded , result או failureReason משתנה. |
מעקב אחרי ההתקדמות
אפשר לעשות זאת באמצעות האירוע progress
. חשוב לזכור ש-downloadTotal
הוא הערך שסיפקתם, או 0
אם לא סיפקתם ערך.
bgFetch.addEventListener('progress', () => {
// If we didn't provide a total, we can't provide a %.
if (!bgFetch.downloadTotal) return;
const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
console.log(`Download progress: ${percent}%`);
});
קבלת הבקשות והתשובות
bgFetch.match('/ep-5.mp3').then(async (record) => {
if (!record) {
console.log('No record found');
return;
}
console.log(`Here's the request`, record.request);
const response = await record.responseReady;
console.log(`And here's the response`, response);
});
record
הוא BackgroundFetchRecord
, והוא נראה כך:
מאפיינים | |
---|---|
request |
Request הבקשה שסופקה. |
responseReady |
Promise<Response> התגובה שנשלפה. התשובה מופיעה אחרי הבטחה כי יכול להיות שהיא עדיין לא התקבלה. אם האחזור נכשל, ה-promise יידחה. |
אירועים של קובצי שירות (service worker)
אירועים | |
---|---|
backgroundfetchsuccess |
הכל אוחזר בהצלחה. |
backgroundfetchfailure |
אחד או יותר מהאחזורים נכשל. |
backgroundfetchabort |
אחזור אחד או יותר נכשל.
האפשרות הזו שימושית רק אם רוצים לבצע ניקוי של נתונים קשורים. |
backgroundfetchclick |
המשתמש לחץ על ממשק המשתמש של התקדמות ההורדה. |
אובייקטי האירוע כוללים את הדברים הבאים:
מאפיינים | |
---|---|
registration |
BackgroundFetchRegistration |
שיטות | |
updateUI({ title, icons }) |
מאפשר לשנות את השם או את הסמלים שהגדרתם בהתחלה. הוספת התיאור היא אופציונלית, אבל היא מאפשרת לכם לספק יותר הקשר במקרה הצורך. אפשר לעשות את זה *פעם אחת* רק במהלך
אירועי backgroundfetchsuccess ו-backgroundfetchfailure . |
תגובה להצלחה או לכשל
כבר ראינו את האירוע progress
, אבל הוא שימושי רק כשהמשתמש פותח דף באתר שלכם. היתרון העיקרי של אחזור ברקע הוא שהדברים ממשיכים לפעול אחרי שהמשתמש עוזב את הדף, או אפילו סוגר את הדפדפן.
אם אחזור הרקע יושלם בהצלחה, האירוע backgroundfetchsuccess
יישלח ל-service worker, ו-event.registration
יהיה הרשמת אחזור הרקע.
אחרי האירוע הזה, לא ניתן לגשת יותר לבקשות ולתשובות שאוחזרו, לכן אם רוצים לשמור אותן, צריך להעביר אותן למקום אחר, כמו cache API.
כמו ברוב האירועים של קובצי שירות (service worker), כדאי להשתמש ב-event.waitUntil
כדי שה-Service Worker ידע מתי האירוע הסתיים.
לדוגמה, ב-service worker:
addEventListener('backgroundfetchsuccess', (event) => {
const bgFetch = event.registration;
event.waitUntil(async function() {
// Create/open a cache.
const cache = await caches.open('downloads');
// Get all the records.
const records = await bgFetch.matchAll();
// Copy each request/response across.
const promises = records.map(async (record) => {
const response = await record.responseReady;
await cache.put(record.request, response);
});
// Wait for the copying to complete.
await Promise.all(promises);
// Update the progress notification.
event.updateUI({ title: 'Episode 5 ready to listen!' });
}());
});
יכול להיות שהכשל נגרם בגלל הודעת 404 אחת, שלא הייתה חשובה לכם, ולכן עדיין כדאי להעתיק תגובות מסוימות למטמון, כפי שמתואר למעלה.
תגובה לקליק
ממשק המשתמש שבו מוצגות התקדמות ההורדה והתוצאה. האירוע backgroundfetchclick
ב-service worker מאפשר לכם להגיב לכך. כמו למעלה, event.registration
תהיה ההרשמה לאחזור ברקע.
הדבר הנפוץ שאפשר לעשות עם האירוע הזה הוא לפתוח חלון:
addEventListener('backgroundfetchclick', (event) => {
const bgFetch = event.registration;
if (bgFetch.result === 'success') {
clients.openWindow('/latest-podcasts');
} else {
clients.openWindow('/download-progress');
}
});
מקורות מידע נוספים
תיקון: גרסה קודמת של המאמר הזה נקראה באופן שגוי 'אחזור ברקע' כ'תקן אינטרנט'. ממשק ה-API לא נמצא כרגע בתהליך יצירת התקן, אבל אפשר למצוא את המפרט ב-WICG כטיוטה של דוח קבוצת קהילה.