Start · Sprachen · JavaScript · Referenz · Atomics.waitAsync()

Atomics.waitAsync()

Methode

Wartet asynchron und nicht blockierend darauf, dass eine Stelle in gemeinsamem Speicher per <code>Atomics.notify()</code> benachrichtigt wird, sofern sie noch den erwarteten Wert enthält.

seit JavaScript ES2024 (Chrome/Edge 87+, Safari 16.4+, Node.js 16+ Kategorie: method-property

Signatur

Atomics.waitAsync(typedArray, index, value, timeout)

Beschreibung

Atomics.waitAsync() ist die asynchrone Variante von Atomics.wait(). Die Methode prüft atomar, ob an der Position index eines gemeinsam genutzten Int32Array oder BigInt64Array noch der Wert value steht. Ist das der Fall, wartet sie auf ein Atomics.notify() für diese Stelle oder auf das Ablaufen des Timeouts. Anders als Atomics.wait() blockiert sie den Thread nicht, sondern gibt sofort ein Objekt zurück, das bei Bedarf ein Promise enthält.

Deshalb lässt sich waitAsync() auch im Haupt-Thread des Browsers verwenden, wo Atomics.wait() verboten ist. Typische Einsatzfälle: Der UI-Thread wartet darauf, dass ein Worker eine Berechnung abgeschlossen hat, oder man baut Synchronisationsbausteine wie Mutexe, Semaphoren und Signale, die sich mit async/await nutzen lassen.

Der Rückgabewert ist ein Objekt { async, value }:

  • async: false: Das Ergebnis steht sofort fest. value ist "not-equal", wenn der Wert bereits abweicht, oder "timed-out", wenn timeout gleich 0 ist.
  • async: true: value ist ein Promise. Es wird mit "ok" erfüllt, sobald eine Benachrichtigung eintrifft, oder mit "timed-out", wenn die Zeit abläuft.

Parameter

Name Typ Default Beschreibung
$typedArray Pflicht Int32Array | BigInt64Array Ein Integer-Array, das auf einem SharedArrayBuffer liegt. Andere Typen oder ein normaler ArrayBuffer lösen einen TypeError aus.
$index Pflicht number Position im Array, an der gewartet wird. Liegt der Wert außerhalb des Arrays, wird ein RangeError ausgelöst.
$value Pflicht number | bigint Erwarteter Wert. Nur wenn die Speicherstelle genau diesen Wert enthält, wird gewartet. Bei BigInt64Array muss es ein bigint sein.
$timeout number Infinity Maximale Wartezeit in Millisekunden. NaN wird als Infinity behandelt, negative Werte als 0.

Rückgabewert

Typ
{ async: false, value: "not-equal" | "timed-out" } | { async: true, value: Promise<"ok" | "timed-out"> }
Beschreibung
Ein Objekt, das angibt, ob das Ergebnis sofort feststeht (async: false) oder über ein Promise geliefert wird (async: true).

Beispiele

Sofortige Ergebnisse: Wert weicht ab oder Timeout 0

const sab = new SharedArrayBuffer(16);
const int32 = new Int32Array(sab);

// An int32[0] steht 0, erwartet wird aber 42
console.log(Atomics.waitAsync(int32, 0, 42));

// Der Wert stimmt, aber das Timeout ist 0
console.log(Atomics.waitAsync(int32, 0, 0, 0));
{ async: false, value: 'not-equal' } { async: false, value: 'timed-out' }

Auf Benachrichtigung warten (mit async/await)

const int32 = new Int32Array(new SharedArrayBuffer(4));

const result = Atomics.waitAsync(int32, 0, 0, 1000);
console.log(result.async); // true

// Später, z. B. aus einem Worker oder per Timer:
setTimeout(() => {
  Atomics.store(int32, 0, 1);
  Atomics.notify(int32, 0);
}, 100);

const status = await result.value;
console.log(status, Atomics.load(int32, 0));
true ok 1

Haupt-Thread wartet auf einen Worker (Node.js)

// main.mjs
import { Worker } from 'node:worker_threads';

const int32 = new Int32Array(new SharedArrayBuffer(4));

const worker = new Worker(`
  const { workerData } = require('node:worker_threads');
  const flag = new Int32Array(workerData);
  // aufwendige Arbeit simulieren
  let sum = 0;
  for (let i = 0; i < 1e8; i++) sum += i;
  Atomics.store(flag, 0, 1);
  Atomics.notify(flag, 0);
`, { eval: true, workerData: int32.buffer });

const waitForDone = async () => {
  const { async, value } = Atomics.waitAsync(int32, 0, 0, 5000);
  const status = async ? await value : value;
  console.log('Worker-Status:', status);
  await worker.terminate();
};

await waitForDone();
Worker-Status: ok

Hilfsfunktion, die alle Fälle einheitlich behandelt

const waitFor = async (arr, index, expected, timeout = Infinity) => {
  const { async, value } = Atomics.waitAsync(arr, index, expected, timeout);
  return async ? value : value; // Promise oder String – await löst beides auf
};

const int32 = new Int32Array(new SharedArrayBuffer(4));
console.log(await waitFor(int32, 0, 0, 50));
timed-out

// Wichtig · Fallstricke

  • Nur mit gemeinsamem Speicher: Das Array muss auf einem SharedArrayBuffer liegen und ein Int32Array oder BigInt64Array sein. Sonst wird ein TypeError ausgelöst.
  • Cross-Origin-Isolation: Im Browser gibt es SharedArrayBuffer nur, wenn die Seite die Header Cross-Origin-Opener-Policy: same-origin und Cross-Origin-Embedder-Policy: require-corp sendet. Prüfen lässt sich das mit crossOriginIsolated.
  • Immer beide Fälle prüfen: value ist nicht immer ein Promise. Bei async: false ist es ein String. Wer direkt result.value.then() aufruft, bekommt dann einen Fehler.
  • Kein Ereignis ohne notify: Wird der Wert nur geändert, ohne Atomics.notify() aufzurufen, endet das Warten erst mit dem Timeout. Ohne Timeout bleibt das Promise für immer offen.
  • Browser-Unterstützung: Chromium und Safari unterstützen die Methode schon länger, Firefox erst seit Kurzem. Vor der Nutzung mit typeof Atomics.waitAsync === 'function' prüfen und bei Bedarf auf Atomics.wait() in einem Worker ausweichen.
  • Die Auflösung des Promise läuft über die Event-Loop. Die Reaktion auf notify() kommt also verzögert und ist nicht für harte Echtzeit-Synchronisation gedacht.