Signatur
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
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();
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();
};
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);
}
};
// 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
localhostverfü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.