Wenn Sie Daten an einen Webserver senden, schlagen die Anfragen manchmal fehl. Möglicherweise hat der Nutzer die Verbindung verloren oder der Server ist ausgefallen. In beiden Fällen möchten Sie häufig versuchen, die Anfragen später noch einmal zu senden.
Die neue BackgroundSync API ist eine ideale Lösung für dieses Problem. Wenn ein Service Worker erkennt, dass eine Netzwerkanfrage fehlgeschlagen ist, kann er sich für den Empfang eines sync
-Ereignisses registrieren. Dieses Ereignis wird gesendet, wenn der Browser denkt, dass die Verbindung wiederhergestellt wurde.
Beachten Sie, dass das Synchronisierungsereignis selbst dann gesendet werden kann, wenn der Nutzer die Anwendung verlassen hat, was es wesentlich effektiver macht als die herkömmliche Methode zum Wiederholen fehlgeschlagener Anfragen.
Die Workbox-Hintergrundsynchronisierung soll die Nutzung der BackgroundSync API und die Einbindung in andere Workbox-Module vereinfachen. Außerdem wird eine Fallback-Strategie für Browser implementiert, die BackgroundSync noch nicht implementieren.
Browser, die die BackgroundSync API unterstützen, geben fehlgeschlagene Anfragen automatisch in Ihrem Namen in einem vom Browser verwalteten Intervall wieder. Dabei wird wahrscheinlich ein exponentieller Backoff zwischen Wiederholungsversuchen verwendet. In Browsern, die die BackgroundSync API nicht nativ unterstützen, versucht die Workbox-Hintergrundsynchronisierung automatisch, bei jedem Start des Service Workers eine erneute Wiedergabe durchzuführen.
Grundlegende Nutzung
Die einfachste Methode zur Verwendung der Hintergrundsynchronisierung besteht darin, Plugin
zu verwenden. Damit werden fehlgeschlagene Anfragen automatisch in die Warteschlange gestellt und wiederholt, wenn zukünftige sync
-Ereignisse ausgelöst werden.
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
bindet sich in den Callback des Plug-ins fetchDidFail
. fetchDidFail
wird nur aufgerufen, wenn eine Ausnahme ausgelöst wird. Dies ist höchstwahrscheinlich auf einen Netzwerkfehler zurückzuführen. Anfragen werden also nicht wiederholt, wenn eine Antwort mit dem Fehlerstatus 4xx
oder 5xx
empfangen wird.
Wenn Sie alle Anfragen wiederholen möchten, die z.B. zum Status 5xx
führen, können Sie Ihrer Strategie ein fetchDidSucceed
-Plug-in hinzufügen:
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.
Erweiterte Nutzung
Die Workbox Background Sync bietet auch eine Queue
-Klasse, die Sie instanziieren und ihr fehlgeschlagene Anfragen hinzufügen können. Die fehlgeschlagenen Anfragen werden in IndexedDB gespeichert und wiederholt, wenn der Browser denkt, dass die Verbindung wiederhergestellt ist, d.h. wenn er das Synchronisierungsereignis empfängt.
Warteschlange erstellen
Um eine Workbox-Hintergrundsynchronisierungswarteschlange zu erstellen, müssen Sie sie mit einem Warteschlangennamen erstellen, der für Ihren Ursprung eindeutig sein muss:
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
Der Warteschlangenname wird als Teil des Tag-Namens verwendet, der vom globalen SyncManager
-Element an register()
übergeben wird. Sie wird auch als Objektspeichername für die IndexedDB-Datenbank verwendet.
Anfrage zur Warteschlange hinzufügen
Nachdem Sie die Warteschlangeninstanz erstellt haben, können Sie ihr fehlgeschlagene Anfragen hinzufügen.
Zum Hinzufügen einer fehlgeschlagenen Anfrage rufen Sie die Methode .pushRequest()
auf. Mit dem folgenden Code werden beispielsweise alle fehlgeschlagenen Anfragen abgefangen und der Warteschlange hinzugefügt:
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());
});
Nach dem Hinzufügen zur Warteschlange wird die Anfrage automatisch wiederholt, wenn der Service Worker das Ereignis sync
empfängt. Das ist der Fall, wenn der Browser feststellt, dass die Verbindung wiederhergestellt ist. Browser, die die BackgroundSync API nicht unterstützen, wiederholen die Warteschlange bei jedem Start des Service Workers noch einmal. Dazu muss die Seite, die den Service Worker steuert, ausgeführt werden, sodass dies nicht ganz so effektiv ist.
Workbox-Hintergrundsynchronisierung wird getestet
Leider ist das Testen von BackgroundSync etwas wenig intuitiv und aus verschiedenen Gründen schwierig.
Gehen Sie am besten so vor, um Ihre Implementierung zu testen:
- Laden Sie eine Seite und registrieren Sie Ihren Service Worker.
- Schalten Sie das Netzwerk Ihres Computers aus oder Ihren Webserver.
- Chrome DEVTOOLS NICHT OFFLINE VERWENDEN. Das Offline-Kästchen in den Entwicklertools wirkt sich nur auf Anfragen von der Seite aus. Service Worker-Anfragen werden weiterhin verarbeitet.
- Stellen Sie Netzwerkanfragen, die mithilfe der Workbox-Hintergrundsynchronisierung in die Warteschlange gestellt werden sollen.
- In
Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
sehen Sie, ob die Anfragen in die Warteschlange gestellt wurden.
- In
- Schalten Sie nun Ihr Netzwerk oder Ihren Webserver ein.
Erzwingen Sie ein frühes
sync
-Ereignis. Rufen Sie dazuChrome DevTools > Application > Service Workers
auf, geben Sie den Tag-Namen vonworkbox-background-sync:<your queue name>
ein, wobei<your queue name>
der Name der von Ihnen festgelegten Warteschlange sein sollte, und klicken Sie dann auf die Schaltfläche „Synchronisieren“.Es sollten Netzwerkanfragen für die fehlgeschlagenen Anfragen verarbeitet werden und die IndexedDB-Daten sollten jetzt leer sein, da die Anfragen erfolgreich wiederholt wurden.
Typen
BackgroundSyncPlugin
Eine Klasse, die den Lebenszyklus-Callback fetchDidFail
implementiert. Dies vereinfacht das Hinzufügen fehlgeschlagener Anfragen zu einer Warteschlange für die Hintergrundsynchronisierung.
Attribute
-
Konstruktor
void
Die Funktion
constructor
sieht so aus:(name: string, options?: QueueOptions) => {...}
-
name
String
Weitere Informationen zu den Parametern finden Sie in der Dokumentation zu
workbox-background-sync.Queue
. -
Optionen
QueueOptions optional
-
Gibt zurück
-
Queue
Eine Klasse, die das Speichern fehlgeschlagener Anfragen in IndexedDB verwaltet und diese später wiederholt. Alle Teile des Speicher- und Wiederholungsprozesses können über Callbacks beobachtet werden.
Attribute
-
Konstruktor
void
Erstellt eine Queue-Instanz mit den angegebenen Optionen
Die Funktion
constructor
sieht so aus:(name: string, options?: QueueOptions) => {...}
-
name
String
Der eindeutige Name für diese Warteschlange. Dieser Name muss eindeutig sein, da er zum Registrieren von Synchronisierungsereignissen und zum Speichern von Anfragen in der für diese Instanz spezifischen IndexedDB verwendet wird. Wird ein doppelter Name erkannt, wird eine Fehlermeldung ausgegeben.
-
Optionen
QueueOptions optional
-
Gibt zurück
-
-
name
String
-
getAll
void
Gibt alle Einträge zurück, die nicht abgelaufen sind (gemäß
maxRetentionTime
). Abgelaufene Einträge werden aus der Warteschlange entfernt.Die Funktion
getAll
sieht so aus:() => {...}
-
Gibt zurück
Promise<QueueEntry[]>
-
-
popRequest
void
Entfernt die letzte Anfrage in der Warteschlange und gibt sie zurück (zusammen mit ihrem Zeitstempel und allen Metadaten). Das zurückgegebene Objekt hat das Format
{request, timestamp, metadata}
.Die Funktion
popRequest
sieht so aus:() => {...}
-
Gibt zurück
Promise<QueueEntry>
-
-
pushRequest
void
Speichert die übergebene Anfrage am Ende der Warteschlange in IndexedDB (mit Zeitstempel und Metadaten).
Die Funktion
pushRequest
sieht so aus:(entry: QueueEntry) => {...}
-
Eintrag
QueueEntry
-
Gibt zurück
Promise<void>
-
-
registerSync
void
Registriert ein Synchronisierungsereignis mit einem für diese Instanz eindeutigen Tag.
Die Funktion
registerSync
sieht so aus:() => {...}
-
Gibt zurück
Promise<void>
-
-
replayRequests
void
Durchläuft jede Anfrage in der Warteschlange und versucht, sie noch einmal abzurufen. Wenn eine Anfrage nicht noch einmal abgerufen werden kann, wird sie an dieselbe Position in der Warteschlange verschoben (wodurch eine Wiederholung für das nächste Synchronisierungsereignis registriert wird).
Die Funktion
replayRequests
sieht so aus:() => {...}
-
Gibt zurück
Promise<void>
-
-
shiftRequest
void
Entfernt die erste Anfrage (zusammen mit ihrem Zeitstempel und allen Metadaten) aus der Warteschlange und gibt sie zurück. Das zurückgegebene Objekt hat das Format
{request, timestamp, metadata}
.Die Funktion
shiftRequest
sieht so aus:() => {...}
-
Gibt zurück
Promise<QueueEntry>
-
-
Größe
void
Gibt die Anzahl der in der Warteschlange vorhandenen Einträge zurück. Beachte, dass abgelaufene Einträge (pro
maxRetentionTime
) auch in dieser Anzahl enthalten sind.Die Funktion
size
sieht so aus:() => {...}
-
Gibt zurück
Versprechen<Zahl>
-
-
unshiftRequest
void
Speichert die übergebene Anfrage mit ihrem Zeitstempel und etwaigen Metadaten in IndexedDB am Anfang der Warteschlange.
Die Funktion
unshiftRequest
sieht so aus:(entry: QueueEntry) => {...}
-
Eintrag
QueueEntry
-
Gibt zurück
Promise<void>
-
QueueOptions
Attribute
-
forceSyncFallback
Boolescher Wert optional
-
maxRetentionTime
Nummer optional
-
onSync
OnSyncCallback optional
QueueStore
Eine Klasse zum Verwalten des Speicherns von Anfragen aus einer Warteschlange in IndexedDB, die für einen leichteren Zugriff nach ihrem Warteschlangennamen indexiert wird.
Die meisten Entwickler müssen nicht direkt auf diese Klasse zugreifen. Sie ist für erweiterte Anwendungsfälle verfügbar.
Attribute
-
Konstruktor
void
Ordnet diese Instanz einer Warteschlangeninstanz zu, sodass hinzugefügte Einträge anhand ihres Warteschlangennamens identifiziert werden können.
Die Funktion
constructor
sieht so aus:(queueName: string) => {...}
-
queueName
String
-
Gibt zurück
-
-
deleteEntry
void
Löscht den Eintrag für die angegebene ID.
WARNUNG: Mit dieser Methode wird nicht sichergestellt, dass der gelöschte Eintrag zu dieser Warteschlange gehört (d.h., er entspricht dem
queueName
). Diese Einschränkung ist jedoch akzeptabel, da diese Klasse nicht öffentlich zugänglich ist. Eine zusätzliche Prüfung würde diese Methode langsamer machen, als sie sein muss.Die Funktion
deleteEntry
sieht so aus:(id: number) => {...}
-
id
Zahl
-
Gibt zurück
Promise<void>
-
-
getAll
void
Gibt alle Einträge im Speicher zurück, die mit
queueName
übereinstimmen.Die Funktion
getAll
sieht so aus:() => {...}
-
Gibt zurück
Promise<QueueStoreEntry[]>
-
-
popEntry
void
Entfernt den letzten Eintrag in der Warteschlange, der mit
queueName
übereinstimmt, und gibt ihn zurück.Die Funktion
popEntry
sieht so aus:() => {...}
-
Gibt zurück
Promise<QueueStoreEntry>
-
-
pushEntry
void
Hängen Sie einen Eintrag an das letzte Mal in der Warteschlange an.
Die Funktion
pushEntry
sieht so aus:(entry: UnidentifiedQueueStoreEntry) => {...}
-
Eintrag
UnidentifiedQueueStoreEntry
-
Gibt zurück
Promise<void>
-
-
shiftEntry
void
Entfernt den ersten Eintrag in der Warteschlange, der mit
queueName
übereinstimmt, und gibt ihn zurück.Die Funktion
shiftEntry
sieht so aus:() => {...}
-
Gibt zurück
Promise<QueueStoreEntry>
-
-
Größe
void
Gibt die Anzahl der Einträge im Speicher zurück, die mit
queueName
übereinstimmen.Die Funktion
size
sieht so aus:() => {...}
-
Gibt zurück
Versprechen<Zahl>
-
-
unshiftEntry
void
Stellen Sie in der Warteschlange einen Eintrag zuerst voran.
Die Funktion
unshiftEntry
sieht so aus:(entry: UnidentifiedQueueStoreEntry) => {...}
-
Eintrag
UnidentifiedQueueStoreEntry
-
Gibt zurück
Promise<void>
-
StorableRequest
Eine Klasse, die das Serialisieren und Deserialisieren von Anfragen vereinfacht, damit sie in IndexedDB gespeichert werden können.
Die meisten Entwickler müssen nicht direkt auf diese Klasse zugreifen. Sie ist für erweiterte Anwendungsfälle verfügbar.
Attribute
-
Konstruktor
void
Akzeptiert ein Objekt mit Anfragedaten, die zum Erstellen eines
Request
verwendet werden können, aber auch in IndexedDB gespeichert werden können.Die Funktion
constructor
sieht so aus:(requestData: RequestData) => {...}
-
requestData
RequestData
Ein Objekt mit Anfragedaten, das
url
sowie alle relevanten Attribute von [requestInit]https://fetch.spec.whatwg.org/#requestinit
enthält.
-
Gibt zurück
-
-
clone
void
Erstellt einen Deep-Klon der Instanz und gibt ihn zurück.
Die Funktion
clone
sieht so aus:() => {...}
-
Gibt zurück
-
-
toObject
void
Gibt einen Deep-Klon des
_requestData
-Instanzobjekts zurück.Die Funktion
toObject
sieht so aus:() => {...}
-
Gibt zurück
RequestData
-
-
toRequest
void
Konvertiert diese Instanz in eine Anfrage.
Die Funktion
toRequest
sieht so aus:() => {...}
-
Gibt zurück
Anfragen
-
-
fromRequest
void
Wandelt ein Anfrageobjekt in ein einfaches Objekt um, das strukturiert oder als JSON-String formatiert werden kann.
Die Funktion
fromRequest
sieht so aus:(request: Request) => {...}
-
Request
Anfragen
-
Gibt zurück
Promise<StorableRequest>
-