Web Locks API
Sicherer Kontext: Diese Funktion ist nur in sicheren Kontexten (HTTPS) in einigen oder allen unterstützenden Browsern verfügbar.
Hinweis: Dieses Feature ist verfügbar in Web Workers.
Die Web Locks API erlaubt es Skripten, die in einem Tab oder einem Worker ausgeführt werden, asynchron eine Sperre zu erwerben, sie zu halten, während Arbeit verrichtet wird, und sie dann wieder freizugeben. Solange sie gehalten wird, kann kein anderes Skript, das im gleichen Ursprung ausgeführt wird, dieselbe Sperre erwerben. Dies ermöglicht es einer Web-Anwendung, die in mehreren Tabs oder Workern läuft, Arbeit und Ressourcenverwendung zu koordinieren.
Konzepte und Verwendung
Eine Sperre ist ein abstraktes Konzept, das eine potenziell geteilte Ressource repräsentiert, identifiziert durch einen vom Web-App gewählten Namen. Zum Beispiel, wenn eine Web-App, die in mehreren Tabs läuft, sicherstellen möchte, dass nur ein Tab Daten zwischen dem Netzwerk und Indexed DB synchronisiert, könnte jeder Tab versuchen, eine "my_net_db_sync" Sperre zu erwerben, doch nur ein Tab wird erfolgreich sein (das Führerwahlschema).
Die API wird wie folgt verwendet:
- Die Sperre wird angefragt.
- Arbeit wird erledigt, während die Sperre in einem asynchronen Task gehalten wird.
- Die Sperre wird automatisch freigegeben, wenn der Task abgeschlossen ist.
navigator.locks.request("my_resource", async (lock) => {
// The lock has been acquired.
await do_something();
await do_something_else();
// Now the lock will be released.
});
Solange eine Sperre gehalten wird, werden Anfragen für dieselbe Sperre von diesem Ausführungskontext oder von anderen Tabs/Workern in die Warteschlange gestellt. Die erste Anfrage in der Warteschlange wird erst gewährt, wenn die Sperre freigegeben wird.
Die API bietet optionale Funktionalitäten, die nach Bedarf genutzt werden können, einschließlich:
- Rückgabe von Werten aus dem asynchronen Task
- geteilte und exklusive Sperrmodi
- bedingte Erfassung
- Diagnosen, um den Zustand der Sperren in einem Ursprung abzufragen
- eine Notlösung, um vor Deadlocks zu schützen
Sperren sind auf Ursprünge beschränkt; die von einem Tab von https://example.com
erworbenen Sperren haben keinen Einfluss auf die von einem Tab von https://example.org:8080
erworbenen Sperren, da es sich um separate Ursprünge handelt.
Der Haupteinstiegspunkt ist navigator.locks.request()
, womit eine Sperre angefordert wird. Es nimmt einen Sperrnamen, eine optionale Menge von Optionen und einen Callback entgegen. Der Callback wird aufgerufen, wenn die Sperre gewährt wird. Die Sperre wird automatisch freigegeben, wenn der Callback zurückkehrt, also ist der Callback normalerweise eine async function, die bewirkt, dass die Sperre erst freigegeben wird, wenn die asynchrone Funktion vollständig abgeschlossen ist.
Die request()
Methode selbst gibt ein Promise zurück, das sich auflöst, sobald die Sperre freigegeben wurde; innerhalb einer async Funktion kann ein Skript await
dem Aufruf hinzufügen, um den asynchronen Code linear ablaufen zu lassen. Zum Beispiel:
await do_something_without_lock();
// Request the lock.
await navigator.locks.request("my_resource", async (lock) => {
// The lock has been acquired.
await do_something_with_lock();
await do_something_else_with_lock();
// Now the lock will be released.
});
// The lock has been released.
await do_something_else_without_lock();
Optionen
Mehrere Optionen können beim Anfordern einer Sperre übergeben werden:
mode
: Der Standardmodus ist "exclusive", aber "shared" kann angegeben werden. Es kann nur einen "exclusive" Inhaber einer Sperre geben, aber mehrere "shared" Anfragen können gleichzeitig gewährt werden. Dies kann verwendet werden, um das Leser-Schreiber-Muster zu implementieren.ifAvailable
: Wenn angegeben, schlägt die Sperranfrage fehl, wenn die Sperre nicht sofort ohne Warten gewährt werden kann. Der Callback wird mitnull
aufgerufen.steal
: Wenn angegeben, werden alle gehaltenen Sperren mit demselben Namen freigegeben, und die Anfrage wird gewährt, wobei alle wartenden Anfragen vorweggenommen werden.signal
: EinAbortSignal
kann übergeben werden, um eine Sperranfrage abzubrechen. Dies kann verwendet werden, um ein Zeitlimit für Anfragen zu implementieren.
Überwachung
Die Methode navigator.locks.query()
kann von Skripten verwendet werden, um den Zustand des Sperr-Managers für den Ursprung zu untersuchen. Dies kann nützlich sein, um beim Debuggen, zum Beispiel, herauszufinden, warum eine Sperre nicht erworben werden konnte. Die Ergebnisse sind ein Schnappschuss des Sperrmanager-Zustands, der gehaltene und angeforderte Sperren und einige zusätzliche Daten (z. B. Modus) zu jedem Zeitpunkt identifiziert, an dem der Schnappschuss gemacht wurde.
Fortgeschrittene Nutzung
Für kompliziertere Fälle, wie das Halten der Sperre für eine beliebige Zeitdauer, kann der Callback ein Promise zurückgeben, das explizit vom Skript aufgelöst wird:
// Capture promise control functions:
let resolve, reject;
const p = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
// Request the lock:
navigator.locks.request(
"my_resource",
// Lock is acquired.
(lock) => p, // Now lock will be held until either resolve() or reject() is called.
);
Deadlocks
Ein Deadlock tritt auf, wenn ein Prozess keinen Fortschritt mehr machen kann, da jeder Teil auf eine Anfrage wartet, die nicht erfüllt werden kann. Dies kann mit dieser API in komplexen Anwendungsfällen auftreten, zum Beispiel, wenn mehrere Sperren außerhalb der Reihenfolge angefordert werden. Wenn Tab 1 Sperre A hält und Tab 2 Sperre B hält, und dann Tab 1 auch Sperre B und Tab 2 auch Sperre A zu erwerben versucht, kann keine Anfrage gewährt werden. Web-Anwendungen können dies durch verschiedene Strategien vermeiden, wie z.B. sicherzustellen, dass Sperranfragen nicht verschachtelt sind, immer gut geordnet sind oder Zeitlimits haben. Beachten Sie, dass solche Deadlocks nur die Sperren selbst und den Code beeinflussen, der von ihnen abhängt; der Browser, andere Tabs und andere Skripte auf der Seite sind nicht betroffen.
Schnittstellen
Lock
-
Bietet den Namen und Modus einer zuvor angeforderten Sperre, die im Callback für
LockManager.request()
empfangen wird. LockManager
-
Bietet Methoden zum Anfordern eines neuen
Lock
-Objekts und zur Abfrage eines bestehendenLock
-Objekts. Um eine Instanz vonLockManager
zu erhalten, rufen Sienavigator.locks
auf.
Erweiterungen zu anderen Schnittstellen
-
Gibt ein
LockManager
-Objekt zurück, das Methoden zum Anfordern eines neuenLock
-Objekts und zur Abfrage eines bestehendenLock
-Objekts bereitstellt. -
Gibt ein
LockManager
-Objekt zurück, das Methoden zum Anfordern eines neuenLock
-Objekts und zur Abfrage eines bestehendenLock
-Objekts bereitstellt.
Spezifikationen
Specification |
---|
Web Locks API |
Browser-Kompatibilität
api.LockManager
BCD tables only load in the browser
api.Lock
BCD tables only load in the browser