Signatur
Beschreibung
Das Ereignis processorerror ist die einzige Möglichkeit, im Haupt-Thread von Fehlern zu erfahren, die im Audio-Rendering-Thread entstehen. Der AudioWorkletProcessor läuft in einem eigenen AudioWorkletGlobalScope. Wirft er eine Ausnahme und fängt sie nicht selbst ab, landet sie nicht im normalen try…catch Ihres Haupt-Codes. Der Browser löst stattdessen am zugehörigen AudioWorkletNode das Ereignis processorerror aus.
Das Ereignis wird in drei Fällen ausgelöst:
- Der Konstruktor des Prozessors wirft eine Ausnahme, zum Beispiel wegen ungültiger
processorOptions. - Die Methode
process()wirft während des Renderns eine Ausnahme. - Eine andere eigene Methode des Prozessors wirft eine Ausnahme, etwa ein
port.onmessage-Handler.
Sie können das Ereignis mit addEventListener("processorerror", …) abonnieren oder die Eigenschaft onprocessorerror setzen. Laut Spezifikation ist das Ereignisobjekt ein ErrorEvent. Es lässt sich nicht abbrechen und steigt nicht im DOM auf (kein Bubbling). Nach einem solchen Fehler ist der Prozessor dauerhaft unbrauchbar: Der Node gibt nur noch Stille aus. Um weiterzumachen, müssen Sie einen neuen AudioWorkletNode erzeugen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Name des Ereignisses: "processorerror". |
|
| $handler Pflicht | (event: ErrorEvent) => void | Die Funktion, die beim Fehler aufgerufen wird. Sie erhält ein ErrorEvent mit den Feldern message, filename, lineno, colno und error. Welche Felder wirklich gefüllt sind, hängt vom Browser ab. |
|
| $options | boolean | AddEventListenerOptions | false | Die üblichen Optionen von addEventListener, zum Beispiel { once: true }. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler bekommt beim Aufruf ein ErrorEvent (in manchen Browsern nur ein einfaches Event).Beispiele
Fehler im Konstruktor des Prozessors abfangen
// Prozessor-Code als Blob-Modul, damit keine eigene Datei nötig ist
const processorCode = `
class GainProcessor extends AudioWorkletProcessor {
constructor(options) {
super();
const gain = options.processorOptions?.gain;
if (typeof gain !== 'number') {
throw new TypeError('processorOptions.gain muss eine Zahl sein');
}
this.gain = gain;
}
process(inputs, outputs) {
const input = inputs[0];
const output = outputs[0];
for (let ch = 0; ch < input.length; ch++) {
for (let i = 0; i < input[ch].length; i++) {
output[ch][i] = input[ch][i] * this.gain;
}
}
return true;
}
}
registerProcessor('gain-processor', GainProcessor);
`;
const ctx = new AudioContext();
const url = URL.createObjectURL(new Blob([processorCode], { type: 'application/javascript' }));
await ctx.audioWorklet.addModule(url);
// Absichtlich falsche Option -> der Konstruktor wirft
const node = new AudioWorkletNode(ctx, 'gain-processor', {
processorOptions: { gain: 'laut' }
});
node.addEventListener('processorerror', (event) => {
console.error('Prozessor abgestürzt:', event.message ?? event.type);
});
onprocessorerror: Node nach einem Absturz automatisch neu erzeugen
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('processors/noise.js');
const createNoiseNode = () => {
const node = new AudioWorkletNode(ctx, 'noise-processor');
node.onprocessorerror = (event) => {
console.warn('noise-processor fehlgeschlagen, wird neu erstellt', event);
node.disconnect();
// Ein abgestürzter Prozessor liefert nur noch Stille -> Node ersetzen
createNoiseNode();
};
node.connect(ctx.destination);
return node;
};
createNoiseNode();
Fehler aus einem port.onmessage-Handler mit einmaligem Listener melden
// processors/filter.js (im AudioWorkletGlobalScope):
// class FilterProcessor extends AudioWorkletProcessor {
// constructor() {
// super();
// this.port.onmessage = ({ data }) => {
// if (data.cutoff < 0) throw new RangeError('cutoff < 0');
// this.cutoff = data.cutoff;
// };
// }
// process() { return true; }
// }
// registerProcessor('filter-processor', FilterProcessor);
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('processors/filter.js');
const filter = new AudioWorkletNode(ctx, 'filter-processor');
filter.addEventListener('processorerror', (event) => {
const detail = event instanceof ErrorEvent ? event.message : '(keine Details)';
// An ein Fehler-Monitoring senden
navigator.sendBeacon('/log', JSON.stringify({ node: 'filter', detail }));
}, { once: true });
filter.port.postMessage({ cutoff: -100 }); // löst processorerror aus
// Wichtig · Fallstricke
- Kein Neustart möglich: Nach
processorerrorbleibt der Prozessor im Fehlerzustand und der Node gibt Stille aus. Trennen Sie ihn mitdisconnect()und erzeugen Sie einen neuenAudioWorkletNode. - Ereignistyp je nach Browser verschieden: Laut Spezifikation ist es ein
ErrorEvent. Ältere oder einzelne Browser liefern aber nur ein einfachesEventohnemessageodererror. Prüfen Sie deshalb mitinstanceof ErrorEventoder dem optionalen Verkettungsoperator (?.), bevor Sie auf die Felder zugreifen. - Sichere Umgebung nötig:
AudioWorkletgibt es nur in sicheren Kontexten (HTTPS oderlocalhost). Eine strenge Content Security Policy (script-src) kann das Laden von Blob-URLs mitaddModule()blockieren. - Listener früh registrieren: Ein Fehler im Konstruktor wird asynchron gemeldet, also nach dem Aufruf von
new AudioWorkletNode(). Registrieren Sie den Listener direkt nach dem Erzeugen des Nodes, spätestens im selben Durchlauf der Ereignisschleife (Task). - Performance: Werfen Sie in
process()keine Ausnahmen, um den Programmablauf zu steuern. Behandeln Sie erwartbare Fehler lieber im Prozessor selbst und melden Sie sie überthis.port.postMessage(). Der Prozessor läuft dann weiter.