Start · Sprachen · JavaScript · Referenz · AsyncDisposableStack.prototype.move()

AsyncDisposableStack.prototype.move()

Methode

Überträgt alle registrierten Entsorger in einen neuen <code>AsyncDisposableStack</code> und markiert den ursprünglichen Stack als entsorgt, ohne die Entsorger aufzurufen.

seit JavaScript ES2026 (Explicit Resource Management); Chrome 134+ Kategorie: method-property

Signatur

AsyncDisposableStack.prototype.move()

Beschreibung

Die Methode move() erzeugt eine neue AsyncDisposableStack-Instanz und übergibt ihr alle Ressourcen und Entsorger, die bisher auf dem aktuellen Stack lagen. Die Reihenfolge bleibt erhalten. Danach gilt der ursprüngliche Stack als entsorgt (disposed === true). Die Entsorger werden dabei nicht aufgerufen, denn die Verantwortung für das Aufräumen geht vollständig auf den neuen Stack über.

Gebraucht wird das vor allem bei Ressourcen, die schrittweise aufgebaut werden: Man sammelt mehrere asynchrone Ressourcen in einem Stack, der mit await using deklariert ist. Scheitert ein Zwischenschritt, räumt der Stack am Blockende automatisch auf. Klappt alles, ruft man am Ende stack.move() auf. So wird beim Verlassen des Blocks nichts entsorgt, und die Ressourcen können an den Aufrufer weitergegeben werden, zum Beispiel als Feld eines Objekts, das selbst [Symbol.asyncDispose]() umsetzt.

Wurde der Stack schon entsorgt (durch disposeAsync() oder einen früheren move()-Aufruf), wirft move() einen ReferenceError.

Rückgabewert

Typ
AsyncDisposableStack
Beschreibung
Ein neuer AsyncDisposableStack, der alle Entsorger des ursprünglichen Stacks in derselben Reihenfolge enthält.

Beispiele

Grundprinzip: Entsorger übertragen

const stack = new AsyncDisposableStack();
stack.defer(async () => console.log('Aufräumen A'));
stack.defer(async () => console.log('Aufräumen B'));

const moved = stack.move();
console.log(stack.disposed);  // alter Stack
console.log(moved.disposed);  // neuer Stack

await stack.disposeAsync();   // hat keine Wirkung mehr
await moved.disposeAsync();   // führt die Entsorger aus (LIFO)
true false Aufräumen B Aufräumen A

Ressourcen sicher aufbauen und an den Aufrufer übergeben

const openResource = async (name) => {
  console.log(`öffne ${name}`);
  return {
    name,
    async [Symbol.asyncDispose]() { console.log(`schließe ${name}`); }
  };
};

class Session {
  #stack;
  constructor(db, cache, stack) {
    this.db = db;
    this.cache = cache;
    this.#stack = stack;
  }
  static async create() {
    await using stack = new AsyncDisposableStack();
    const db = stack.use(await openResource('db'));
    const cache = stack.use(await openResource('cache'));
    // Alles hat geklappt: Eigentum an die Session übergeben
    return new Session(db, cache, stack.move());
  }
  async [Symbol.asyncDispose]() {
    await this.#stack.disposeAsync();
  }
}

{
  await using session = await Session.create();
  console.log('arbeite mit', session.db.name, session.cache.name);
}
öffne db öffne cache arbeite mit db cache schließe cache schließe db

Fehler beim Aufbau: automatisches Aufräumen

const createPair = async () => {
  await using stack = new AsyncDisposableStack();
  stack.defer(async () => console.log('Verbindung 1 geschlossen'));
  throw new Error('Verbindung 2 fehlgeschlagen');
  // wird nicht erreicht, move() findet also nicht statt
  return stack.move();
};

try {
  await createPair();
} catch (err) {
  console.log('Fehler:', err.message);
}
Verbindung 1 geschlossen Fehler: Verbindung 2 fehlgeschlagen

ReferenceError bei bereits entsorgtem Stack

const stack = new AsyncDisposableStack();
await stack.disposeAsync();
try {
  stack.move();
} catch (err) {
  console.log(err.name);
}
ReferenceError

// Wichtig · Fallstricke

  • Kein Aufräumen: move() ruft keinen Entsorger auf. Wer den zurückgegebenen Stack verwirft, ohne ihn zu entsorgen, hinterlässt offene Ressourcen.
  • ReferenceError: Ist der Stack bereits entsorgt, wirft move() einen Fehler. Das gilt auch für einen zweiten move()-Aufruf.
  • Nur einmal übertragen: Der alte Stack ist danach dauerhaft unbrauchbar. Aufrufe von use(), adopt() oder defer() auf ihm werfen ebenfalls einen ReferenceError. disposeAsync() dagegen läuft stillschweigend ohne Wirkung durch.
  • Unterklassen: Der Rückgabewert ist immer ein einfacher AsyncDisposableStack, keine Instanz einer eigenen Unterklasse.
  • Kompatibilität: Das gehört zum noch recht neuen Proposal Explicit Resource Management. Unterstützt wird es in Chromium ab 134, in Firefox ab 141 und in Node.js ab 24. Safari unterstützt es noch nicht. Für ältere Umgebungen braucht man ein Polyfill (z. B. core-js) und für await using gegebenenfalls einen Transpiler (TypeScript 5.2+, Babel).