ในปี 2015 เราได้เปิดตัวการซิงค์ในเบื้องหลังซึ่งทำให้ Service Worker ให้เลื่อนงานออกไปจนกว่าผู้ใช้จะเชื่อมต่อ ซึ่งหมายความว่าผู้ใช้สามารถพิมพ์ ส่งข้อความ กดส่ง และออกจากเว็บไซต์โดยที่รู้ว่าจะมีการส่งข้อความในตอนนี้หรือเมื่อ มีการเชื่อมต่อ
เป็นฟีเจอร์ที่มีประโยชน์ แต่ต้องทำให้โปรแกรมทำงานของบริการต้องทำงานอยู่ในช่วงระยะเวลาของ ดึงข้อมูล กรณีนี้ไม่ใช่ปัญหาสำหรับงานสั้นๆ อย่างการส่งข้อความ แต่หากงานนั้นใช้เวลา การใช้งานนานเกินไป เบราว์เซอร์จะทำให้โปรแกรมทำงานของบริการไม่ได้ทำงาน มิฉะนั้นอาจเสี่ยงต่อความเป็นส่วนตัวของผู้ใช้ และ แบตเตอรี่
ดังนั้น ในกรณีที่คุณต้องการดาวน์โหลดสิ่งที่อาจต้องใช้เวลานาน เช่น ภาพยนตร์ พอดแคสต์ หรือ ในระดับต่างๆ ของเกม ซึ่งเป็นหน้าที่ของการดึงข้อมูลในเบื้องหลัง
การดึงข้อมูลในเบื้องหลังสามารถใช้ได้โดยค่าเริ่มต้นตั้งแต่ Chrome 74
ด้านล่างนี้เป็นการสาธิตสั้นๆ เพียง 2 นาทีเพื่อแสดงสภาพของสิ่งต่างๆ แบบดั้งเดิม เทียบกับการใช้การดึงข้อมูลในเบื้องหลัง:
ลองใช้การสาธิตด้วยตัวคุณเองและเรียกดูโค้ด
วิธีการทำงาน
การดึงข้อมูลในเบื้องหลังมีลักษณะดังนี้
- โดยคุณกำหนดให้เบราว์เซอร์ดำเนินการดึงข้อมูลเป็นกลุ่มในพื้นหลัง
- เบราว์เซอร์จะดึงข้อมูลเหล่านั้นและแสดงความคืบหน้าให้กับผู้ใช้
- เมื่อการดึงข้อมูลเสร็จสมบูรณ์หรือล้มเหลว เบราว์เซอร์จะเปิด 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
รับอาร์กิวเมนต์ 3 ตัว ดังนี้
พารามิเตอร์ | |
---|---|
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
ฉันจะ
อธิบายรายละเอียดของเรื่องนั้นในภายหลัง คำสัญญาจะปฏิเสธหากผู้ใช้เลือกไม่รับการดาวน์โหลด หรือ
พารามิเตอร์ที่ระบุไม่ถูกต้อง
การส่งคำขอหลายรายการสำหรับการดึงข้อมูลในเบื้องหลังครั้งเดียวช่วยให้คุณรวมสิ่งที่ ให้แก่ผู้ใช้ ตัวอย่างเช่น ภาพยนตร์อาจแบ่งออกเป็น 1, 000 รายการ (โดยทั่วไปจะมี 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> ล้มเลิกการดึงข้อมูลในเบื้องหลัง สัญญาที่ส่งกลับมาจะแก้ไขเป็น "จริง" หากล้มเลิกการดึงข้อมูลสำเร็จ |
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> คำตอบที่ดึงข้อมูล การตอบกลับจะเป็นไปตามสัญญาเนื่องจากอาจยังไม่ได้รับ คำมั่นสัญญา จะปฏิเสธหากดึงข้อมูลไม่สำเร็จ |
กิจกรรมของ Service Worker
กิจกรรม | |
---|---|
backgroundfetchsuccess |
ดึงข้อมูลทุกอย่างสำเร็จแล้ว |
backgroundfetchfailure |
การเรียกข้อมูลล้มเหลวอย่างน้อย 1 รายการ |
backgroundfetchabort |
ดึงข้อมูลไม่สำเร็จอย่างน้อย 1 รายการ
ซึ่งจะเป็นประโยชน์มากในกรณีที่คุณต้องการล้างข้อมูลที่เกี่ยวข้องเท่านั้น |
backgroundfetchclick |
ผู้ใช้คลิก UI ความคืบหน้าในการดาวน์โหลด |
ออบเจ็กต์เหตุการณ์มีข้อมูลต่อไปนี้
พร็อพเพอร์ตี้ | |
---|---|
registration |
BackgroundFetchRegistration |
เมธอด | |
updateUI({ title, icons }) |
ช่วยให้คุณเปลี่ยนชื่อ/ไอคอนที่ตั้งค่าไว้ในตอนแรกได้ ขั้นตอนนี้เป็นขั้นตอนที่ไม่บังคับ แต่จะช่วยให้คุณ
จะให้บริบทเพิ่มเติมหากจำเป็น คุณสามารถทำเช่นนี้ได้เพียง *ครั้งเดียว* ระหว่าง
backgroundfetchsuccess และ backgroundfetchfailure กิจกรรม |
การตอบสนองต่อความสำเร็จ/ความล้มเหลว
เราได้เห็นเหตุการณ์ progress
แล้ว แต่จะมีประโยชน์ก็ต่อเมื่อผู้ใช้เปิดหน้าเว็บ
เว็บไซต์ของคุณ ประโยชน์หลักของการดึงข้อมูลในเบื้องหลังคือสิ่งต่างๆ จะทำงานต่อไปหลังจากที่ผู้ใช้ออกจาก
หน้าเว็บ หรือแม้กระทั่งปิดเบราว์เซอร์
หากการดึงข้อมูลในเบื้องหลังเสร็จสมบูรณ์ โปรแกรมทำงานของบริการจะได้รับ
backgroundfetchsuccess
และ event.registration
จะเป็นการลงทะเบียนการดึงข้อมูลในเบื้องหลัง
หลังจากเหตุการณ์นี้ คำขอและการตอบกลับที่ดึงมาจะไม่สามารถเข้าถึงได้อีก ดังนั้นหากต้องการ เก็บไว้ และย้ายไปไว้ที่อื่น เช่น API แคช
เช่นเดียวกับเหตุการณ์ของ Service Worker ส่วนใหญ่ ให้ใช้ event.waitUntil
เพื่อให้โปรแกรมทำงานของบริการทราบเมื่อเกิดเหตุการณ์
เสร็จสมบูรณ์
ตัวอย่างเช่น ในโปรแกรมทำงานของบริการ
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 รายการเดียว ซึ่งอาจไม่ได้สำคัญสำหรับคุณ ดังนั้นอาจ แต่ก็ควรที่จะคัดลอกการตอบกลับบางอย่างลงในแคชดังเช่นข้างต้น
แสดงความรู้สึกต่อการคลิก
UI ที่แสดงความคืบหน้าในการดาวน์โหลดและผลลัพธ์เป็นแบบคลิกได้ เหตุการณ์ 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 ในรูปแบบรายงานกลุ่มชุมชนฉบับร่าง