Signatur
Beschreibung
WindowClient ist eine Unterklasse von Client aus der ServiceWorker-API. Ein solches Objekt steht für ein Dokument in einem Browsing-Kontext (Tab, Fenster, iframe), das vom aktiven Service Worker gesteuert wird. Zusätzlich zu den geerbten Eigenschaften id, url, type und frameType und der Methode postMessage() bietet es fensterspezifische Funktionen.
focused(nur lesbar,boolean): gibt an, ob der Client gerade den Fokus hat.visibilityState(nur lesbar,"visible" | "hidden"): gibt an, ob das Dokument sichtbar ist.ancestorOrigins(nur lesbar,string[]): die Ursprünge der übergeordneten Browsing-Kontexte. Wird nicht von allen Browsern unterstützt.focus(): holt das Fenster in den Vordergrund und gibt einPromise<WindowClient>zurück.navigate(url): lädt eine neue URL im Client und gibt einPromise<WindowClient | null>zurück.
Einen eigenen Konstruktor gibt es nicht. Du bekommst WindowClient-Objekte nur innerhalb eines Service Workers, und zwar über clients.matchAll({ type: "window" }), clients.get(id) oder clients.openWindow(url). Am häufigsten braucht man das in einem notificationclick-Handler: Ist die App schon in einem Tab offen, wird dieser fokussiert, sonst wird ein neues Fenster geöffnet.
Weitere typische Einsätze: Seiten nach einem Update des Service Workers gezielt neu laden oder umleiten und prüfen, ob ein Tab gerade sichtbar ist, bevor eine Benachrichtigung angezeigt wird.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $url Pflicht | string | Parameter von WindowClient.navigate(url): Ziel-URL, relativ zur URL des Clients. Muss denselben Ursprung wie der Service Worker haben, sonst wird das Promise mit null erfüllt (Navigation zu einem fremden Ursprung). |
Rückgabewert
Clients-Methoden im Service Worker. focus() gibt Promise<WindowClient> zurück, navigate() gibt Promise<WindowClient | null> zurück.Beispiele
Beim Klick auf eine Benachrichtigung einen offenen Tab fokussieren oder ein neues Fenster öffnen
// sw.js
self.addEventListener('notificationclick', (event) => {
event.notification.close();
const targetUrl = new URL('/inbox', self.location.origin).href;
event.waitUntil((async () => {
const windows = await clients.matchAll({ type: 'window', includeUncontrolled: true });
// Bereits offenen Tab mit passender URL suchen
const existing = windows.find((c) => c.url === targetUrl);
if (existing) {
return existing.focus();
}
return clients.openWindow(targetUrl);
})());
});
Zustand aller gesteuerten Fenster auslesen
// sw.js – z. B. in einem message- oder push-Handler
const logWindowClients = async () => {
const windows = await clients.matchAll({ type: 'window' });
for (const win of windows) {
console.log(win.id, win.url, win.focused, win.visibilityState);
}
};
self.addEventListener('message', (event) => {
if (event.data === 'debug-clients') {
event.waitUntil(logWindowClients());
}
});
Nach der Aktivierung eines neuen Service Workers alle Tabs neu laden
// sw.js
self.addEventListener('activate', (event) => {
event.waitUntil((async () => {
await clients.claim(); // Kontrolle über offene Seiten übernehmen
const windows = await clients.matchAll({ type: 'window' });
await Promise.all(
windows.map((win) => win.navigate(win.url)) // gleiche URL = Neuladen
);
})());
});
Push-Nachricht nur anzeigen, wenn kein Tab sichtbar ist
// sw.js
self.addEventListener('push', (event) => {
const data = event.data?.json() ?? { title: 'Neue Nachricht' };
event.waitUntil((async () => {
const windows = await clients.matchAll({ type: 'window' });
const visible = windows.some((w) => w.visibilityState === 'visible');
if (visible) {
// Sichtbare Seite direkt informieren statt Benachrichtigung anzeigen
windows.forEach((w) => w.postMessage({ type: 'push', data }));
return;
}
return self.registration.showNotification(data.title);
})());
});
// Wichtig · Fallstricke
- Nur im Service Worker verfügbar: Im Hauptthread (
window) gibt esWindowClientnicht. Das Interface lässt sich auch nicht mitnewerzeugen. focus()braucht eine Nutzeraktion: Der Aufruf klappt nur innerhalb eines Handlers, der durch eine Benachrichtigung ausgelöst wurde (notificationclick). Sonst wird das Promise mit einemInvalidAccessErrorabgelehnt. Dasselbe gilt fürclients.openWindow().navigate()funktioniert nur bei gesteuerten Clients: Für Clients, die nicht vom aufrufenden Worker gesteuert werden (z. B. ausincludeUncontrolled: true), wird das Promise mit einemTypeErrorabgelehnt. Führt die Navigation zu einem fremden Ursprung, ist das Ergebnisnull.- Kontext aktiv halten: Promise-Ketten immer in
event.waitUntil()einhängen. Sonst kann der Browser den Worker vorzeitig beenden. - URL-Vergleich:
client.urlist immer eine absolute URL, eventuell mit Query-String oder Hash. Für robuste Vergleiche bessernew URL(client.url).pathnameverwenden. - Kompatibilität:
focused,visibilityState,focus()undnavigate()werden von allen modernen Browsern unterstützt.ancestorOriginsfehlt in Firefox. Service Worker laufen nur in sicheren Kontexten (HTTPS oderlocalhost).