Start · Sprachen · JavaScript · Referenz · PushManager

PushManager

Schnittstelle

Das Interface <code>PushManager</code> der Push-API verwaltet Push-Abonnements eines Service Workers: anlegen, abrufen und den Berechtigungsstatus prüfen.

seit JavaScript Baseline 2023: Chrome 42+, Firefox 44+, Edge 17+, Kategorie: webapi

Signatur

interface PushManager

Beschreibung

PushManager ist die Schnittstelle, über die eine Web-Anwendung Push-Nachrichten von einem Server empfangen kann, auch wenn die Seite gerade nicht geöffnet ist. Einen eigenen Konstruktor gibt es nicht. Man erreicht die Instanz über die Eigenschaft pushManager einer ServiceWorkerRegistration, also z. B. mit registration.pushManager.

Die wichtigsten Mitglieder:

  • subscribe(options): Legt ein neues Abonnement an (oder gibt ein bestehendes zurück) und liefert ein Promise<PushSubscription>. Das Abonnement enthält den Endpoint (die URL des Push-Dienstes) und die Schlüssel p256dh und auth zur Verschlüsselung.
  • getSubscription(): Liefert das aktuelle Abonnement oder null, wenn keines besteht.
  • permissionState(options): Liefert den Berechtigungsstatus 'granted', 'denied' oder 'prompt'.
  • PushManager.supportedContentEncodings (statisch): Liste der unterstützten Verschlüsselungsverfahren, z. B. ['aes128gcm', 'aesgcm'].

Der typische Ablauf sieht so aus: Service Worker registrieren, Berechtigung einholen, mit subscribe() und dem öffentlichen VAPID-Schlüssel des eigenen Servers abonnieren und das Abonnement per JSON.stringify() an das Backend schicken. Das Backend sendet dann über das Web-Push-Protokoll verschlüsselte Nachrichten an den Endpoint. Im Service Worker kommen sie als push-Event an.

Parameter

Name Typ Default Beschreibung
$options.userVisibleOnly boolean false Parameter von subscribe() und permissionState(). Legt fest, dass jede Push-Nachricht eine sichtbare Benachrichtigung auslöst. Chrome akzeptiert nur true.
$options.applicationServerKey ArrayBuffer | TypedArray | DataView | string Öffentlicher VAPID-Schlüssel des Anwendungsservers (ECDSA P-256). Als Zeichenkette muss er Base64url-kodiert sein. Chrome und Safari verlangen ihn.

Rückgabewert

Typ
PushManager
Beschreibung
Erreichbar über ServiceWorkerRegistration.pushManager. subscribe() und getSubscription() liefern Promise<PushSubscription | null>, permissionState() liefert Promise<PermissionState>.

Beispiele

PushManager-Instanz über die Service-Worker-Registrierung holen

if ('serviceWorker' in navigator && 'PushManager' in window) {
  const registration = await navigator.serviceWorker.register('/sw.js');
  const { pushManager } = registration;
  console.log(pushManager instanceof PushManager);
  console.log(PushManager.supportedContentEncodings);
} else {
  console.warn('Push wird nicht unterstützt');
}
true ["aes128gcm", "aesgcm"]

Push abonnieren und das Abonnement an den Server senden

const VAPID_PUBLIC_KEY = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';

const urlBase64ToUint8Array = (base64) => {
  const padding = '='.repeat((4 - (base64.length % 4)) % 4);
  const raw = atob((base64 + padding).replace(/-/g, '+').replace(/_/g, '/'));
  return Uint8Array.from(raw, (c) => c.charCodeAt(0));
};

const subscribeUser = async () => {
  const permission = await Notification.requestPermission();
  if (permission !== 'granted') return null;

  const registration = await navigator.serviceWorker.ready;
  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
  });

  await fetch('/api/push/subscribe', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(subscription)
  });
  return subscription;
};

// Nur nach einer Nutzeraktion aufrufen
document.querySelector('#push-btn').addEventListener('click', subscribeUser);

Bestehendes Abonnement prüfen und kündigen

const registration = await navigator.serviceWorker.ready;
const state = await registration.pushManager.permissionState({ userVisibleOnly: true });
console.log('Berechtigung:', state);

const subscription = await registration.pushManager.getSubscription();
if (subscription) {
  console.log('Endpoint:', subscription.endpoint);
  const ok = await subscription.unsubscribe();
  console.log('Abgemeldet:', ok);
} else {
  console.log('Kein Abonnement vorhanden');
}
Berechtigung: granted Endpoint: https://fcm.googleapis.com/fcm/send/... Abgemeldet: true

Push-Nachricht im Service Worker empfangen (sw.js)

self.addEventListener('push', (event) => {
  const data = event.data?.json() ?? { title: 'Neuigkeit', body: '' };
  event.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: '/icons/icon-192.png'
    })
  );
});

// Wichtig · Fallstricke

  • Sicherer Kontext nötig: Die Push-API gibt es nur über HTTPS (oder localhost) und nur mit aktivem Service Worker.
  • Berechtigung nur nach Nutzeraktion: Safari und Firefox verlangen, dass subscribe() bzw. Notification.requestPermission() von einer Nutzeraktion (z. B. einem Klick) ausgelöst wird. Sonst wird der Aufruf mit NotAllowedError abgelehnt.
  • Sichtbare Benachrichtigung ist Pflicht: Chrome und Safari erlauben nur userVisibleOnly: true. Zeigt der Service Worker bei einem push-Event keine Benachrichtigung an, blendet der Browser eine eigene Standardmeldung ein oder entzieht die Berechtigung.
  • iOS/iPadOS: Ab 16.4 funktioniert Push nur in Web-Apps, die zum Home-Bildschirm hinzugefügt wurden. Ein Web-App-Manifest ist nötig.
  • Abonnements können ablaufen: Push-Dienste können einen Endpoint ungültig machen (Server erhält HTTP 404/410). Deshalb beim Start getSubscription() prüfen, bei Bedarf neu abonnieren und die Serverseite aktualisieren.
  • Sicherheit: Der Endpoint ist ein geheimer Schlüssel für den Versand. Ihn nur über HTTPS übertragen und mit Bezug zum angemeldeten Nutzer speichern. Den privaten VAPID-Schlüssel nie im Client ablegen.
  • Veraltet: Die alten Methoden hasPermission() und register() sowie PushSubscription.subscriptionId wurden entfernt und sollten nicht mehr verwendet werden.