Start · Sprachen · JavaScript · Referenz · WindowClient

WindowClient

Schnittstelle

Repräsentiert im Service Worker ein Fenster oder einen Tab, der vom Worker gesteuert wird. Das Fenster lässt sich damit fokussieren, umleiten oder nach seinem Zustand abfragen.

seit JavaScript Baseline: alle modernen Browser (Chrome 42+, Firef Kategorie: webapi

Signatur

interface WindowClient extends Client

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 ein Promise<WindowClient> zurück.
  • navigate(url): lädt eine neue URL im Client und gibt ein Promise<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

Typ
WindowClient
Beschreibung
Instanzen gibt es nur über 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());
  }
});
3f2a…-uuid https://example.com/ true visible 9b1c…-uuid https://example.com/settings false hidden

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 es WindowClient nicht. Das Interface lässt sich auch nicht mit new erzeugen.
  • focus() braucht eine Nutzeraktion: Der Aufruf klappt nur innerhalb eines Handlers, der durch eine Benachrichtigung ausgelöst wurde (notificationclick). Sonst wird das Promise mit einem InvalidAccessError abgelehnt. Dasselbe gilt für clients.openWindow().
  • navigate() funktioniert nur bei gesteuerten Clients: Für Clients, die nicht vom aufrufenden Worker gesteuert werden (z. B. aus includeUncontrolled: true), wird das Promise mit einem TypeError abgelehnt. Führt die Navigation zu einem fremden Ursprung, ist das Ergebnis null.
  • Kontext aktiv halten: Promise-Ketten immer in event.waitUntil() einhängen. Sonst kann der Browser den Worker vorzeitig beenden.
  • URL-Vergleich: client.url ist immer eine absolute URL, eventuell mit Query-String oder Hash. Für robuste Vergleiche besser new URL(client.url).pathname verwenden.
  • Kompatibilität: focused, visibilityState, focus() und navigate() werden von allen modernen Browsern unterstützt. ancestorOrigins fehlt in Firefox. Service Worker laufen nur in sicheren Kontexten (HTTPS oder localhost).