Start · Sprachen · JavaScript · Referenz · TaskSignal

TaskSignal

Schnittstelle

Signalobjekt der Prioritized Task Scheduling API, mit dem sich Aufgaben aus <code>scheduler.postTask()</code> abbrechen und ihre Priorität nachträglich ändern lassen.

seit JavaScript Chromium 94+ (Chrome, Edge, Opera), Firefox 142+; Kategorie: webapi

Signatur

interface TaskSignal extends AbortSignal

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", …) oder onprioritychange): wird ausgelöst, wenn sich die Priorität ändert. Das Event-Objekt ist ein TaskPriorityChangeEvent mit der Eigenschaft previousPriority.
  • Geerbt von AbortSignal: aborted, reason, throwIfAborted() und das Event abort.
  • TaskSignal.any(signals, init) (statisch): erzeugt ein kombiniertes TaskSignal.

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);
true background Prefetch fertig

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;
Priorität: background -> user-blocking Bilder vorbereitet

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);
}
AbortError - Nicht mehr nötig true

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);
true user-visible

// 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 einen TypeError. Nutzen Sie new TaskController() oder TaskSignal.any().
  • Übergibt man an postTask() sowohl signal als auch priority, gilt die feste priority. Die Aufgabe ignoriert dann Prioritätsänderungen des Signals, lässt sich aber weiterhin abbrechen.
  • Ein normales AbortSignal kann ebenfalls als signal übergeben werden. Damit lässt sich die Aufgabe aber nur abbrechen, ihre Priorität kann man nicht ändern.
  • Ruft man setPriority() innerhalb eines prioritychange-Handlers für dasselbe Signal erneut auf, entsteht ein NotAllowedError. 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.