בשנת 2015 השקנו את סנכרון ברקע, שמאפשר ל-service worker לדחות את העבודה עד שהמשתמש יקבל חיבור. המשמעות היא שהמשתמש יכול להקליד הודעה, ללחוץ על 'שליחה' ולצאת מהאתר, בידיעה שההודעה תישלח עכשיו או כשהוא יהיה מחובר.
זו תכונה שימושית, אבל היא דורשת שקובץ השירות (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 האם יש גישה לבקשות או לתשובות הבסיסיות? אחרי שהערך הזה יהיה שגוי, לא ניתן יהיה להשתמש ב- |
Methods | |
abort() |
הפונקציה מחזירה את הערך Promise<boolean> כדי לבטל את האחזור ברקע. אם האחזור בוטל בהצלחה, ה-promise המוחזר יתקבל עם הערך true. |
matchAll(request, opts) |
הפונקציה מחזירה את הערך Promise<Array<BackgroundFetchRecord>> . מקבלים את הבקשות והתשובות. הארגומנטים כאן זהים לארגומנטים של 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 |
Methods | |
updateUI({ title, icons }) |
מאפשרת לשנות את השם או את הסמלים שהגדרתם בהתחלה. הוספת התיאור היא אופציונלית, אבל היא מאפשרת לכם לספק יותר הקשר במקרה הצורך. אפשר לעשות זאת רק *פעם אחת* במהלך אירועי backgroundfetchsuccess ו-backgroundfetchfailure . |
תגובה להצלחה או לכשל
כבר ראינו את האירוע progress
, אבל הוא שימושי רק כשהמשתמש פותח דף באתר שלכם. היתרון העיקרי של אחזור ברקע הוא שהדברים ממשיכים לפעול אחרי שהמשתמש עוזב את הדף, או אפילו סוגר את הדפדפן.
אם אחזור הרקע יושלם בהצלחה, האירוע backgroundfetchsuccess
יישלח ל-service worker, ו-event.registration
יהיה הרשמת אחזור הרקע.
אחרי האירוע הזה, לא ניתן לגשת יותר לבקשות ולתשובות שאוחזרו, לכן אם רוצים לשמור אותן, צריך להעביר אותן למקום אחר, כמו cache API.
כמו ברוב האירועים של שירות העבודה, צריך להשתמש ב-event.waitUntil
כדי ששירות העבודה ידע מתי האירוע הושלם.
לדוגמה, ב-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 כטיוטה של דוח קבוצת קהילה.