เมื่อคุณส่งข้อมูลไปยังเว็บเซิร์ฟเวอร์ บางครั้งคำขออาจล้มเหลว อาจเป็นเพราะผู้ใช้ขาดการเชื่อมต่อ หรืออาจเป็นเพราะเซิร์ฟเวอร์หยุดทำงาน หรือในกรณีเหล่านี้คุณมักต้องการลองส่งคำขออีกครั้งในภายหลัง
BackgroundSync API ใหม่
เป็นวิธีแก้ปัญหาที่ดีที่สุดสำหรับปัญหานี้ เมื่อ Service Worker ตรวจพบว่าคำขอเครือข่ายล้มเหลว โปรแกรมจะลงทะเบียนเพื่อรับเหตุการณ์ sync
ซึ่งระบบจะนำส่งเมื่อเบราว์เซอร์คิดว่าการเชื่อมต่อกลับมาเป็นปกติ
โปรดทราบว่าคุณสามารถส่งเหตุการณ์การซิงค์ได้แม้ว่าผู้ใช้จะออกจากแอปพลิเคชันไปแล้ว ซึ่งทำให้มีประสิทธิภาพมากกว่าวิธีการลองส่งคำขอที่ล้มเหลวซ้ำแบบเดิม
Workbox Background Sync ได้รับการออกแบบมาเพื่อใช้ BackgroundSync API ได้ง่ายขึ้นและผสานรวมการใช้งานกับโมดูล Workbox อื่นๆ รวมถึงใช้กลยุทธ์สำรองสำหรับเบราว์เซอร์ที่ยังไม่ได้ใช้ BackgroundSync ด้วย
เบราว์เซอร์ที่รองรับ BackgroundSync API จะเล่นคำขอที่ล้มเหลวซ้ำโดยอัตโนมัติในนามของคุณในช่วงเวลาที่เบราว์เซอร์จัดการ โดยมีแนวโน้มที่จะใช้การย้อนกลับแบบทวีคูณระหว่างการพยายามเล่นซ้ำ ในเบราว์เซอร์ที่ไม่รองรับ BackgroundSync API แล้ว Workbox Background Sync จะพยายามเล่นซ้ำโดยอัตโนมัติทุกครั้งที่ Service Worker เริ่มทำงาน
การใช้งานพื้นฐาน
วิธีที่ง่ายที่สุดในการใช้การซิงค์ในเบื้องหลังคือการใช้ Plugin
ซึ่งจะจัดคิวคำขอที่ล้มเหลวโดยอัตโนมัติ แล้วลองอีกครั้งเมื่อเหตุการณ์ sync
ในอนาคตเริ่มทำงาน
import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
maxRetentionTime: 24 * 60, // Retry for max of 24 Hours (specified in minutes)
});
registerRoute(
/\/api\/.*\/*.json/,
new NetworkOnly({
plugins: [bgSyncPlugin],
}),
'POST'
);
BackgroundSyncPlugin
จะเชื่อมต่อกับ fetchDidFail
โค้ดเรียกกลับและ fetchDidFail
จะมีการเรียกใช้ก็ต่อเมื่อมีข้อยกเว้น ซึ่งน่าจะเป็นเพราะเครือข่ายล้มเหลว ซึ่งหมายความว่าระบบจะไม่ส่งคำขอซ้ำหากได้รับการตอบกลับซึ่งมีสถานะข้อผิดพลาด 4xx
หรือ 5xx
ที่ได้รับ
หากต้องการลองคำขอทั้งหมดที่ส่งผลให้เกิด เช่น สถานะ 5xx
อีกครั้ง คุณสามารถทำได้โดยเพิ่มปลั๊กอิน fetchDidSucceed
ลงในกลยุทธ์ ดังนี้
const statusPlugin = {
fetchDidSucceed: ({response}) => {
if (response.status >= 500) {
// Throwing anything here will trigger fetchDidFail.
throw new Error('Server error.');
}
// If it's not 5xx, use the response as-is.
return response;
},
};
// Add statusPlugin to the plugins array in your strategy.
การใช้งานขั้นสูง
Workbox Background Sync ยังมีคลาส Queue
ซึ่งคุณยืนยันและเพิ่มคำขอที่ล้มเหลวได้ ระบบจะจัดเก็บคำขอที่ล้มเหลวไว้ใน IndexedDB และจะลองใหม่เมื่อเบราว์เซอร์คิดว่าการเชื่อมต่อกลับมาใช้งานได้ (เช่น เมื่อได้รับเหตุการณ์การซิงค์)
การสร้างคิว
หากต้องการสร้างคิวการซิงค์เบื้องหลังของ Workbox คุณต้องสร้างคิวโดยใช้ชื่อคิว (ซึ่งต้องไม่ซ้ำกันสำหรับต้นทางของคุณ) โดยทำดังนี้
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
ชื่อคิวใช้เป็นส่วนหนึ่งของชื่อแท็กที่ได้รับ register()
โดยส่วนกลาง SyncManager
และยังใช้ชื่อเป็น Object Store สำหรับฐานข้อมูล IndexedDB
การเพิ่มคำขอลงในคิว
เมื่อสร้างอินสแตนซ์คิวแล้ว คุณจะเพิ่มคำขอที่ล้มเหลวไปยังอินสแตนซ์นั้นได้
คุณเพิ่มคำขอที่ไม่สำเร็จโดยเรียกใช้เมธอด .pushRequest()
ตัวอย่างเช่น โค้ดต่อไปนี้จะตรวจจับคำขอที่ล้มเหลวและเพิ่มลงในคิว
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
self.addEventListener('fetch', event => {
// Add in your own criteria here to return early if this
// isn't a request that should use background sync.
if (event.request.method !== 'POST') {
return;
}
const bgSyncLogic = async () => {
try {
const response = await fetch(event.request.clone());
return response;
} catch (error) {
await queue.pushRequest({request: event.request});
return error;
}
};
event.respondWith(bgSyncLogic());
});
เมื่อเพิ่มลงในคิวแล้ว ระบบจะพยายามส่งคำขออีกครั้งโดยอัตโนมัติเมื่อโปรแกรมทำงานของบริการได้รับเหตุการณ์ sync
(ซึ่งจะเกิดขึ้นเมื่อเบราว์เซอร์คิดว่าการเชื่อมต่อกลับมาเป็นปกติ) เบราว์เซอร์ที่ไม่รองรับ BackgroundSync API จะลองคิวใหม่ทุกครั้งที่โปรแกรมทำงานของบริการเริ่มต้น การตั้งค่านี้กำหนดให้หน้าที่ควบคุม Service Worker ทำงาน ดังนั้นจึงไม่ค่อยมีประสิทธิภาพมากนัก
การทดสอบการซิงค์ในเบื้องหลังของ Workbox
ที่น่าเศร้าที่การทดสอบ BackgroundSync นั้นค่อนข้างยุ่งยากและยากด้วยเหตุผลหลายประการ
วิธีที่ดีที่สุดในการทดสอบการติดตั้งใช้งานคือทำสิ่งต่อไปนี้
- โหลดหน้าเว็บและลงทะเบียน Service Worker
- ปิดเครือข่ายของคอมพิวเตอร์หรือปิดเว็บเซิร์ฟเวอร์
- ห้ามใช้ Chrome DEVTOOLS แบบออฟไลน์ ช่องทำเครื่องหมายออฟไลน์ในเครื่องมือสำหรับนักพัฒนาเว็บจะส่งผลต่อคำขอจากหน้าเว็บเท่านั้น คำขอของ Service Worker จะต้องดำเนินการต่อไป
- สร้างคำขอเครือข่ายที่ควรอยู่ในคิวด้วย Workbox Background Sync
- คุณตรวจสอบคำขอที่เข้าคิวได้โดยดูที่
Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
- คุณตรวจสอบคำขอที่เข้าคิวได้โดยดูที่
- แล้วเปิดเครือข่ายหรือเว็บเซิร์ฟเวอร์ของคุณ
บังคับใช้เหตุการณ์
sync
ก่อนกำหนดโดยไปที่Chrome DevTools > Application > Service Workers
ป้อนชื่อแท็กของworkbox-background-sync:<your queue name>
โดยที่<your queue name>
ควรเป็น ชื่อของคิวที่คุณตั้งไว้ แล้วคลิกปุ่ม "ซิงค์"คุณควรจะเห็นคำขอเครือข่ายที่ได้รับการดำเนินการสำหรับคำขอที่ล้มเหลว และข้อมูล IndexedDB ควรว่างเปล่าเนื่องจากคำขอได้รับการเล่นซ้ำสำเร็จแล้ว
ประเภท
BackgroundSyncPlugin
คลาสที่ใช้การเรียกกลับสำหรับวงจร fetchDidFail
ซึ่งช่วยให้คุณเพิ่มคำขอที่ล้มเหลวไปยังคิวการซิงค์ในเบื้องหลังได้ง่ายขึ้น
พร็อพเพอร์ตี้
-
เครื่องมือสร้าง
void
ฟังก์ชัน
constructor
มีลักษณะดังนี้(name: string, options?: QueueOptions) => {...}
-
ชื่อ
string
ดูรายละเอียดพารามิเตอร์ในเอกสารประกอบ
workbox-background-sync.Queue
-
ตัวเลือก
QueueOptions ไม่บังคับ
-
returns
-
Queue
คลาสสำหรับจัดการการจัดเก็บคำขอที่ล้มเหลวใน IndexedDB และลองอีกครั้งในภายหลัง ทุกส่วนของกระบวนการจัดเก็บและเล่นซ้ำจะสังเกตได้ด้วยการเรียกกลับ
พร็อพเพอร์ตี้
-
เครื่องมือสร้าง
void
สร้างอินสแตนซ์ของคิวด้วยตัวเลือกที่ระบุ
ฟังก์ชัน
constructor
มีลักษณะดังนี้(name: string, options?: QueueOptions) => {...}
-
ชื่อ
string
ชื่อที่ไม่ซ้ำกันสำหรับคิวนี้ ชื่อนี้ต้องไม่ซ้ำกันเนื่องจากใช้เพื่อลงทะเบียนเหตุการณ์การซิงค์และคำขอจัดเก็บใน IndexedDB เฉพาะสำหรับอินสแตนซ์นี้ ระบบจะแสดงข้อผิดพลาด หากตรวจพบชื่อซ้ำ
-
ตัวเลือก
QueueOptions ไม่บังคับ
-
returns
-
-
ชื่อ
string
-
getAll
void
แสดงรายการทั้งหมดที่ยังไม่หมดอายุ (ต่อ
maxRetentionTime
) ระบบจะนำรายการที่หมดอายุออกจากคิวฟังก์ชัน
getAll
มีลักษณะดังนี้() => {...}
-
returns
Promise<QueueEntry[]>
-
-
popRequest
void
นำคำขอสุดท้ายในคิวออกและแสดงผล (พร้อมการประทับเวลาและข้อมูลเมตา) ออบเจ็กต์ที่แสดงผลจะอยู่ในรูปแบบ
{request, timestamp, metadata}
ฟังก์ชัน
popRequest
มีลักษณะดังนี้() => {...}
-
returns
Promise<QueueEntry>
-
-
pushRequest
void
จัดเก็บคำขอที่ส่งผ่านใน IndexedDB (พร้อมด้วยการประทับเวลาและข้อมูลเมตา) ที่ส่วนท้ายของคิว
ฟังก์ชัน
pushRequest
มีลักษณะดังนี้(entry: QueueEntry) => {...}
-
รายการ
QueueEntry
-
returns
Promise<void>
-
-
registerSync
void
ลงทะเบียนเหตุการณ์การซิงค์ซึ่งมีแท็กเฉพาะสำหรับอินสแตนซ์นี้
ฟังก์ชัน
registerSync
มีลักษณะดังนี้() => {...}
-
returns
Promise<void>
-
-
replayRequests
void
วนซ้ำคำขอแต่ละรายการในคิวและพยายามดึงข้อมูลอีกครั้ง หากคำขอใดดึงข้อมูลอีกครั้งไม่สำเร็จ ระบบจะกลับไปที่ตำแหน่งเดิมในคิว (ซึ่งจะลงทะเบียนอีกครั้งสำหรับกิจกรรมการซิงค์ถัดไป)
ฟังก์ชัน
replayRequests
มีลักษณะดังนี้() => {...}
-
returns
Promise<void>
-
-
shiftRequest
void
นำออกและแสดงผลคำขอแรกในคิว (พร้อมกับการประทับเวลาและข้อมูลเมตา) ออบเจ็กต์ที่แสดงผลจะอยู่ในรูปแบบ
{request, timestamp, metadata}
ฟังก์ชัน
shiftRequest
มีลักษณะดังนี้() => {...}
-
returns
Promise<QueueEntry>
-
-
ขนาด
void
แสดงผลจำนวนรายการที่แสดงในคิว โปรดทราบว่ารายการที่หมดอายุ (ต่อ
maxRetentionTime
) จะรวมอยู่ในจำนวนนี้ด้วยฟังก์ชัน
size
มีลักษณะดังนี้() => {...}
-
returns
คำมั่นสัญญา<number>
-
-
unshiftRequest
void
จัดเก็บคำขอที่ส่งผ่านใน IndexedDB (พร้อมการประทับเวลาและข้อมูลเมตา) ที่จุดเริ่มต้นของคิว
ฟังก์ชัน
unshiftRequest
มีลักษณะดังนี้(entry: QueueEntry) => {...}
-
รายการ
QueueEntry
-
returns
Promise<void>
-
QueueOptions
พร็อพเพอร์ตี้
-
forceSyncFallback
บูลีน ไม่บังคับ
-
maxRetentionTime
ตัวเลข ไม่บังคับ
-
onSync
OnSyncCallback ไม่บังคับ
QueueStore
คลาสสำหรับจัดการการจัดเก็บคำขอจากคิวใน IndexedDB จัดทำดัชนีตามชื่อคิวของคิวเพื่อให้เข้าถึงได้ง่ายขึ้น
นักพัฒนาซอฟต์แวร์ส่วนใหญ่ไม่จำเป็นต้องเข้าถึงชั้นเรียนนี้โดยตรง เพราะมีการเปิดเผยไว้สำหรับ Use Case ขั้นสูง
พร็อพเพอร์ตี้
-
เครื่องมือสร้าง
void
เชื่อมโยงอินสแตนซ์นี้กับอินสแตนซ์คิวเพื่อให้ระบุรายการที่เพิ่มได้โดยใช้ชื่อคิว
ฟังก์ชัน
constructor
มีลักษณะดังนี้(queueName: string) => {...}
-
queueName
string
-
returns
-
-
deleteEntry
void
ลบรายการของรหัสที่ระบุ
คำเตือน: เมธอดนี้ไม่ได้รับประกันว่ารายการที่ถูกลบจะเป็นของคิวนี้ (กล่าวคือ ตรงกับ
queueName
) แต่ข้อจำกัดนี้เป็นสิ่งที่ยอมรับได้เพราะคลาสนี้จะไม่เผยแพร่ต่อสาธารณะ การตรวจสอบเพิ่มเติมจะทำให้วิธีนี้ช้ากว่าที่ควรจะเป็นฟังก์ชัน
deleteEntry
มีลักษณะดังนี้(id: number) => {...}
-
id
ตัวเลข
-
returns
Promise<void>
-
-
getAll
void
แสดงรายการทั้งหมดใน Store ที่ตรงกับ
queueName
ฟังก์ชัน
getAll
มีลักษณะดังนี้() => {...}
-
returns
Promise<QueueStoreEntry[]>
-
-
popEntry
void
นำรายการสุดท้ายในคิวที่ตรงกับ
queueName
ออกและแสดงผลฟังก์ชัน
popEntry
มีลักษณะดังนี้() => {...}
-
returns
Promise<QueueStoreEntry>
-
-
pushEntry
void
เพิ่มรายการต่อท้ายในคิว
ฟังก์ชัน
pushEntry
มีลักษณะดังนี้(entry: UnidentifiedQueueStoreEntry) => {...}
-
รายการ
UnidentifiedQueueStoreEntry
-
returns
Promise<void>
-
-
shiftEntry
void
นำรายการแรกในคิวที่ตรงกับ
queueName
ออกและแสดงผลฟังก์ชัน
shiftEntry
มีลักษณะดังนี้() => {...}
-
returns
Promise<QueueStoreEntry>
-
-
ขนาด
void
แสดงผลจำนวนรายการใน Store ที่ตรงกับ
queueName
ฟังก์ชัน
size
มีลักษณะดังนี้() => {...}
-
returns
คำมั่นสัญญา<number>
-
-
unshiftEntry
void
เพิ่มรายการไว้หน้ารายการก่อนในคิว
ฟังก์ชัน
unshiftEntry
มีลักษณะดังนี้(entry: UnidentifiedQueueStoreEntry) => {...}
-
รายการ
UnidentifiedQueueStoreEntry
-
returns
Promise<void>
-
StorableRequest
คลาสที่ง่ายขึ้นในการเรียงอันดับคำขอและแยกอนุกรมวิธาน เพื่อให้จัดเก็บคำขอเหล่านั้นใน IndexedDB
นักพัฒนาซอฟต์แวร์ส่วนใหญ่ไม่จำเป็นต้องเข้าถึงชั้นเรียนนี้โดยตรง เพราะมีการเปิดเผยไว้สำหรับ Use Case ขั้นสูง
พร็อพเพอร์ตี้
-
เครื่องมือสร้าง
void
ยอมรับออบเจ็กต์ของข้อมูลคำขอที่ใช้สร้าง
Request
ได้ แต่สามารถจัดเก็บไว้ใน IndexedDB ได้ด้วยฟังก์ชัน
constructor
มีลักษณะดังนี้(requestData: RequestData) => {...}
-
requestData
RequestData
ออบเจ็กต์ของข้อมูลคำขอที่มี
url
รวมถึงพร็อพเพอร์ตี้ที่เกี่ยวข้องของ [requestInit]https://fetch.spec.whatwg.org/#requestinit
-
returns
-
-
การโคลน
void
สร้างและแสดงผลการโคลนของอินสแตนซ์ในระดับลึก
ฟังก์ชัน
clone
มีลักษณะดังนี้() => {...}
-
returns
-
-
toObject
void
แสดงผลการโคลนของออบเจ็กต์
_requestData
ของอินสแตนซ์ฟังก์ชัน
toObject
มีลักษณะดังนี้() => {...}
-
returns
RequestData
-
-
toRequest
void
แปลงอินสแตนซ์นี้เป็นคำขอ
ฟังก์ชัน
toRequest
มีลักษณะดังนี้() => {...}
-
returns
ส่งคำขอ
-
-
fromRequest
void
แปลงออบเจ็กต์คำขอเป็นออบเจ็กต์ธรรมดาที่โคลนหรือสตริง JSON ได้
ฟังก์ชัน
fromRequest
มีลักษณะดังนี้(request: Request) => {...}
-
ส่งคำขอ
ส่งคำขอ
-
returns
Promise<StorableRequest>
-