Start · Sprachen · JavaScript · Referenz · WorkerNavigator.usb

WorkerNavigator.usb

Eigenschaft

Schreibgeschützte Eigenschaft, die in einem Worker das <code>USB</code>-Objekt liefert und damit Zugriff auf die WebUSB-API außerhalb des Hauptthreads ermöglicht.

seit JavaScript Chromium-Browser (Chrome/Edge/Opera) – experimente Kategorie: webapi

Signatur

WorkerNavigator.usb

Beschreibung

Die Eigenschaft navigator.usb innerhalb eines Workers (WorkerNavigator) liefert dasselbe USB-Objekt wie Navigator.usb im Fenster. Darüber kannst du bereits freigegebene USB-Geräte abfragen, öffnen und Daten mit ihnen austauschen, ohne den Hauptthread zu blockieren. Das ist besonders dann nützlich, wenn du große Datenmengen überträgst (z. B. Firmware-Updates, Messdaten, Kamerastreams) oder rechenintensiv mit den empfangenen Daten weiterarbeitest.

Wichtig ist die Arbeitsteilung: Die Berechtigung für ein Gerät kann nur im Fenster-Kontext erteilt werden, weil USB.requestDevice() eine Benutzeraktion (z. B. einen Klick) und einen Auswahldialog braucht. Im Worker gibt es requestDevice() deshalb nicht. Dort holst du freigegebene Geräte mit USB.getDevices() und reagierst über die Ereignisse connect und disconnect auf das Anstecken oder Abziehen.

Die Eigenschaft ist mit [SameObject] gekennzeichnet, gibt bei jedem Zugriff also dasselbe Objekt zurück. Sie ist nur in sicheren Kontexten (HTTPS oder localhost) vorhanden und nur in Browsern, die WebUSB unterstützen. Prüfe deshalb immer mit 'usb' in navigator, ob sie verfügbar ist.

Rückgabewert

Typ
USB
Beschreibung
Das USB-Objekt des aktuellen Worker-Kontexts. Es bietet getDevices() sowie die Ereignisse connect/disconnect. Ist WebUSB nicht verfügbar, fehlt die Eigenschaft ganz (undefined).

Beispiele

Freigegebene Geräte im Worker auflisten

// usb-worker.js
const listDevices = async () => {
  if (!('usb' in navigator)) {
    postMessage({ error: 'WebUSB wird in diesem Worker nicht unterstützt.' });
    return;
  }
  const devices = await navigator.usb.getDevices();
  postMessage(devices.map(d => ({
    name: d.productName,
    vendorId: d.vendorId.toString(16),
    productId: d.productId.toString(16)
  })));
};

listDevices();
[{ name: 'Arduino Uno', vendorId: '2341', productId: '43' }]

Berechtigung im Fenster holen, Datenübertragung im Worker

// main.js – läuft im Fenster
const worker = new Worker('transfer-worker.js');

document.querySelector('#connect').addEventListener('click', async () => {
  // requestDevice() geht nur im Fenster und nur nach Benutzeraktion
  await navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] });
  worker.postMessage({ cmd: 'start' });
});

worker.onmessage = ({ data }) => console.log('Worker:', data);

// transfer-worker.js – läuft im Worker
onmessage = async ({ data }) => {
  if (data.cmd !== 'start') return;
  const [device] = await navigator.usb.getDevices();
  if (!device) return postMessage('Kein freigegebenes Gerät gefunden');

  await device.open();
  if (device.configuration === null) await device.selectConfiguration(1);
  await device.claimInterface(0);

  const result = await device.transferIn(1, 64); // Endpunkt 1, 64 Byte
  postMessage(`Empfangen: ${result.data.byteLength} Byte`);
  await device.close();
};
Worker: Empfangen: 64 Byte

Auf das An- und Abstecken im Worker reagieren

// usb-worker.js
const onConnect = ({ device }) =>
  postMessage(`Verbunden: ${device.productName}`);
const onDisconnect = ({ device }) =>
  postMessage(`Getrennt: ${device.productName}`);

navigator.usb.addEventListener('connect', onConnect);
navigator.usb.addEventListener('disconnect', onDisconnect);

// Alternativ über die on-Properties:
// navigator.usb.onconnect = onConnect;

// Überwachung beenden
onmessage = ({ data }) => {
  if (data === 'stop') {
    navigator.usb.removeEventListener('connect', onConnect);
    navigator.usb.removeEventListener('disconnect', onDisconnect);
  }
};
Verbunden: Arduino Uno

// Wichtig · Fallstricke

  • Kein requestDevice() im Worker: Neue Geräte können nur im Fenster über einen Auswahldialog nach einer Benutzeraktion freigegeben werden. Der Worker sieht nur Geräte, die dem Ursprung (Origin) schon erlaubt wurden.
  • Browser-Unterstützung: WebUSB gibt es nur in Chromium-Browsern (Chrome, Edge, Opera) auf dem Desktop und unter Android. Firefox und Safari unterstützen es nicht. Die Unterstützung in Workern kann je nach Worker-Typ unterschiedlich sein (Dedicated Worker ja, Service Worker nur eingeschränkt, z. B. in Erweiterungen). Deshalb immer per Feature-Erkennung prüfen.
  • Sicherer Kontext: Nur über HTTPS oder localhost verfügbar. Zusätzlich kann eine Permissions Policy (usb) den Zugriff in iframes und damit auch in deren Workern sperren.
  • Exklusiver Zugriff: Ein Interface kann immer nur von einem Kontext gleichzeitig beansprucht werden (claimInterface()). Öffne dasselbe Gerät also nicht parallel im Fenster und im Worker.
  • Einige Geräteklassen (z. B. Tastaturen, Massenspeicher, Audio/Video) blockiert der Browser aus Sicherheitsgründen. Für sie bleibt getDevices() leer bzw. claimInterface() schlägt fehl.