Start · Sprachen · JavaScript · Referenz · Lock

Lock

Schnittstelle

Das <code>Lock</code>-Interface der Web Locks API steht für eine erteilte Sperre und liefert deren Namen (<code>name</code>) und Modus (<code>mode</code>).

seit JavaScript Baseline 2022: Chrome 69+, Edge 79+, Firefox 96+, Kategorie: webapi

Signatur

interface Lock

Beschreibung

Ein Lock-Objekt steht für eine Sperre, die über navigator.locks.request() angefordert und erteilt wurde. Es wird an die Callback-Funktion übergeben, sobald die Sperre gehalten wird. Die Sperre bleibt so lange aktiv, bis der Callback zurückkehrt oder das von ihm zurückgegebene Promise erfüllt bzw. abgelehnt wird.

Das Interface ist bewusst schlank und hat nur zwei schreibgeschützte Eigenschaften:

  • Lock.name: der beim Anfordern übergebene Name der Ressource (string).
  • Lock.mode: der Zugriffsmodus, entweder "exclusive" (Standard, nur ein Halter) oder "shared" (mehrere Leser gleichzeitig).

Web Locks koordinieren den Zugriff auf gemeinsame Ressourcen, z. B. IndexedDB-Transaktionen, Token-Aktualisierungen oder Synchronisationsvorgänge. Das funktioniert über mehrere Tabs, Fenster und Worker desselben Ursprungs (Origin) hinweg. Man erzeugt Lock-Objekte nie selbst: Sie werden ausschließlich vom LockManager bereitgestellt.

Wird ifAvailable: true gesetzt und ist die Sperre gerade belegt, erhält der Callback statt eines Lock-Objekts den Wert null. Diesen Fall sollte man immer prüfen.

Rückgabewert

Typ
Lock
Beschreibung
Wird vom LockManager an den Callback von navigator.locks.request() übergeben. Bei ifAvailable: true und belegter Sperre ist der Wert null. Eigenschaften: name: string, mode: "exclusive" | "shared".

Beispiele

Exklusive Sperre anfordern und Lock-Eigenschaften lesen

await navigator.locks.request('cache-update', async (lock) => {
  console.log(lock instanceof Lock); // Lock-Objekt vom LockManager
  console.log(`Sperre: ${lock.name}, Modus: ${lock.mode}`);
  // kritischer Abschnitt: nur ein Tab/Worker gleichzeitig
  await new Promise((r) => setTimeout(r, 500));
});
console.log('Sperre freigegeben');
true Sperre: cache-update, Modus: exclusive Sperre freigegeben

Gemeinsame Lesesperre (shared)

const readConfig = () =>
  navigator.locks.request('config', { mode: 'shared' }, async (lock) => {
    console.log(`${lock.name} gelesen im Modus ${lock.mode}`);
    return JSON.parse(localStorage.getItem('config') ?? '{}');
  });

// Mehrere Leser dürfen gleichzeitig zugreifen
const [a, b] = await Promise.all([readConfig(), readConfig()]);
console.log(a, b);
config gelesen im Modus shared config gelesen im Modus shared {} {}

Nur ausführen, wenn die Sperre frei ist (ifAvailable)

const syncOnce = () =>
  navigator.locks.request('sync', { ifAvailable: true }, async (lock) => {
    if (!lock) {
      console.log('Synchronisation läuft bereits in einem anderen Tab');
      return false;
    }
    console.log(`Starte Sync mit Sperre "${lock.name}"`);
    await fetch('/api/sync', { method: 'POST' });
    return true;
  });

const started = await syncOnce();
console.log('Gestartet:', started);
Starte Sync mit Sperre "sync" Gestartet: true

Gehaltene und wartende Sperren abfragen

navigator.locks.request('job', async () => {
  const { held, pending } = await navigator.locks.query();
  held.forEach(({ name, mode, clientId }) =>
    console.log('gehalten:', name, mode, clientId)
  );
  console.log('wartend:', pending.length);
});
gehalten: job exclusive 8b1e… wartend: 0

// Wichtig · Fallstricke

  • Nur in sicherem Kontext: Die Web Locks API steht nur über HTTPS bzw. localhost zur Verfügung. Sonst ist navigator.locks undefined.
  • Lebensdauer: Die Sperre wird freigegeben, sobald das Promise des Callbacks abgeschlossen ist, nicht erst, wenn das Lock-Objekt vom Garbage Collector entfernt wird. Gibt der Callback kein Promise zurück, wird die Sperre sofort nach der synchronen Ausführung wieder freigegeben. Ein Promise, das nie abschließt, hält die Sperre dauerhaft und blockiert alle anderen Anforderungen (Deadlock-Gefahr).
  • null bei ifAvailable: Ist die Sperre belegt, wird der Callback mit null aufgerufen. Wer lock.name ohne Prüfung liest, bekommt einen TypeError.
  • Keine Konstruktion: new Lock() wirft einen TypeError, denn Instanzen entstehen nur über den LockManager.
  • Geltungsbereich: Sperren gelten nur innerhalb desselben Ursprungs (Origin) und derselben Storage-Partition. Sie koordinieren nicht über Geräte oder Server hinweg.
  • Namen, die mit - beginnen, sind reserviert und führen zu einem NotSupportedError.
  • Verfügbar in Fenstern und Workern. In Node.js gibt es die API erst ab Version 22 (experimentell); in älteren Umgebungen vorher auf 'locks' in navigator prüfen.