Signatur
Beschreibung
TaskSignal erweitert AbortSignal um eine Priorität. Ein solches Signal übergibt man in der Option signal an scheduler.postTask(). Damit kann man alle damit verknüpften Aufgaben gemeinsam abbrechen (wie mit jedem AbortSignal) oder ihre Priorität ändern, auch nachdem sie schon eingeplant wurden, solange sie noch nicht laufen.
Normalerweise erzeugt man ein TaskSignal nicht direkt, sondern über einen TaskController: new TaskController({ priority }) stellt das Signal unter controller.signal bereit. controller.abort() bricht ab, controller.setPriority() ändert die Priorität. Seit neueren Versionen gibt es außerdem die statische Methode TaskSignal.any(signals, { priority }). Sie kombiniert mehrere Abbruch-Signale und übernimmt wahlweise eine feste Priorität oder die Priorität eines anderen TaskSignal.
Wichtige Bestandteile:
TaskSignal.priority(nur lesbar): aktuelle Priorität, also"user-blocking","user-visible"oder"background".- Event
prioritychange(addEventListener("prioritychange", …)oderonprioritychange): wird ausgelöst, wenn sich die Priorität ändert. Das Event-Objekt ist einTaskPriorityChangeEventmit der EigenschaftpreviousPriority. - Geerbt von
AbortSignal:aborted,reason,throwIfAborted()und das Eventabort. TaskSignal.any(signals, init)(statisch): erzeugt ein kombiniertesTaskSignal.
Man verwendet TaskSignal, wenn Arbeit in Blöcke zerlegt und nach Wichtigkeit geplant werden soll. Beispiele sind Vorab-Laden (Prefetching), Analysecode oder Rendern außerhalb des sichtbaren Bereichs, dessen Priorität steigen soll, sobald der Nutzer ihn braucht.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $signals Pflicht | Iterable<AbortSignal> | Nur bei TaskSignal.any(): die Signale, deren Abbruch das neue Signal ebenfalls abbricht. |
|
| $init.priority | "user-blocking"|"user-visible"|"background"|TaskSignal | "user-visible" | Nur bei TaskSignal.any(): eine feste Priorität oder ein TaskSignal, dessen Priorität das neue Signal übernimmt und mitverfolgt. |
Beispiele
TaskSignal über TaskController erzeugen und Aufgabe einplanen
const controller = new TaskController({ priority: 'background' });
const { signal } = controller;
console.log(signal instanceof AbortSignal); // TaskSignal erbt von AbortSignal
console.log(signal.priority);
const result = await scheduler.postTask(() => 'Prefetch fertig', { signal });
console.log(result);
Priorität zur Laufzeit ändern und auf prioritychange reagieren
const controller = new TaskController({ priority: 'background' });
controller.signal.addEventListener('prioritychange', (event) => {
console.log(`Priorität: ${event.previousPriority} -> ${event.target.priority}`);
});
const task = scheduler.postTask(() => console.log('Bilder vorbereitet'), {
signal: controller.signal,
});
// Nutzer scrollt zum Bereich – Arbeit wird plötzlich dringend
controller.setPriority('user-blocking');
await task;
Eingeplante Aufgabe abbrechen
const controller = new TaskController();
const task = scheduler.postTask(() => console.log('wird nie ausgeführt'), {
signal: controller.signal,
delay: 1000,
});
controller.abort(new DOMException('Nicht mehr nötig', 'AbortError'));
try {
await task;
} catch (err) {
console.log(err.name, '-', err.message);
console.log(controller.signal.aborted);
}
TaskSignal.any(): Timeout und Priorität kombinieren
const prioController = new TaskController({ priority: 'user-visible' });
const combined = TaskSignal.any(
[prioController.signal, AbortSignal.timeout(5000)],
{ priority: prioController.signal } // folgt der Priorität von prioController
);
const data = await scheduler.postTask(() => JSON.parse('{"ok":true}'), {
signal: combined,
});
console.log(data.ok, combined.priority);
// Wichtig · Fallstricke
- Browser-Kompatibilität: Die API wird nur in Chromium-Browsern (ab Version 94) und in neueren Firefox-Versionen unterstützt, Safari unterstützt sie nicht. Vor der Nutzung sollte man sie prüfen (
if ('scheduler' in globalThis && 'postTask' in scheduler)) oder ein Polyfill einsetzen.TaskSignal.any()ist neuer als der Rest der API und muss gesondert geprüft werden. - Es gibt keinen öffentlichen Konstruktor.
new TaskSignal()wirft einenTypeError. Nutzen Sienew TaskController()oderTaskSignal.any(). - Übergibt man an
postTask()sowohlsignalals auchpriority, gilt die festepriority. Die Aufgabe ignoriert dann Prioritätsänderungen des Signals, lässt sich aber weiterhin abbrechen. - Ein normales
AbortSignalkann ebenfalls alssignalübergeben werden. Damit lässt sich die Aufgabe aber nur abbrechen, ihre Priorität kann man nicht ändern. - Ruft man
setPriority()innerhalb einesprioritychange-Handlers für dasselbe Signal erneut auf, entsteht einNotAllowedError. Die Priorität auf ihren aktuellen Wert zu setzen, löst kein Event aus. - Eine Prioritätsänderung wirkt nur auf Aufgaben, die noch nicht gestartet sind. Eine bereits laufende Aufgabe wird nicht unterbrochen.