[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/await [Back]  [Original]

await - JavaScript | MDN

Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.

View in English Always switch to English

await

Baseline
Weitgehend verfgbar
*

Diese Funktion ist gut etabliert und funktioniert auf vielen Gerten und in vielen Browserversionen. Sie ist seit Mrz 2017 browserbergreifend verfgbar.

* Einige Teile dieser Funktion werden mglicherweise unterschiedlich gut untersttzt.

Der await Operator wird verwendet, um auf ein Promise zu warten und dessen Erfllungswert zu erhalten. Er kann nur innerhalb einer async function oder auf oberster Ebene eines modul verwendet werden.

In diesem Artikel

Syntax

js
await expression

Parameter

expression

Ein Promise, ein thenable object oder ein beliebiger Wert, auf den gewartet werden soll.

Rckgabewert

Der Erfllungswert des Promises oder des thenable objects oder, wenn der Ausdruck nicht thenable ist, der eigene Wert des Ausdrucks.

Ausnahmen

Wirft den Ablehnungsgrund, wenn das Promise oder das thenable object abgelehnt wird.

Beschreibung

await wird blicherweise verwendet, um Promises zu entpacken, indem ein Promise als expression bergeben wird. Die Verwendung von await pausiert die Ausfhrung seiner umgebenden async Funktion, bis das Promise abgeschlossen ist (d.h. erfllt oder abgelehnt wird). Wenn die Ausfhrung fortgesetzt wird, entspricht der Wert des await-Ausdrucks dem des erfllten Promises.

Wenn das Promise abgelehnt wird, wirft der await-Ausdruck den abgelehnten Wert. Die Funktion, die den await-Ausdruck enthlt, wird im Stack-Trace des Fehlers erscheinen. Andernfalls, wenn das abgelehnte Promise nicht erwartet oder sofort zurckgegeben wird, wird die aufrufende Funktion nicht im Stack-Trace erscheinen.

Der expression-Ausdruck wird auf die gleiche Weise aufgelst wie Promise.resolve(): Er wird immer in ein natives Promise umgewandelt und dann erwartet. Wenn der expression-Ausdruck ein:

  • Natives Promise (was bedeutet, dass expression zu Promise oder einer Unterklasse gehrt und expression.constructor === Promise ist): Das Promise wird direkt verwendet und nativ ohne Aufruf von then() erwartet.
  • Thenable object (einschlielich nicht-nativen Promises, Polyfill, Proxy, Kindklasse, etc.): Ein neues Promise wird mit dem nativen Promise()-Konstruktor erstellt, indem die then()-Methode des Objekts aufgerufen und ein Handler bergeben wird, der den resolve-Callback aufruft.
  • Nicht-thenable Wert: Ein bereits erflltes Promise wird erstellt und verwendet.

Selbst wenn das verwendete Promise bereits erfllt ist, pausiert die Ausfhrung der async Funktion bis zum nchsten Tick. In der Zwischenzeit wird der Aufrufer der async Funktion erneut ausgefhrt. Siehe das Beispiel unten.

Da await nur innerhalb von async Funktionen und Modulen gltig ist, die selbst asynchron sind und Promises zurckgeben, blockiert der await-Ausdruck niemals den Hauptthread und verschiebt nur die Ausfhrung von Code, der tatschlich vom Ergebnis abhngt, d.h. alles, was nach dem await-Ausdruck kommt.

Beispiele

Warten auf ein Promise, um erfllt zu werden

Wenn ein Promise an einen await-Ausdruck bergeben wird, wartet dieser, bis das Promise erfllt ist und gibt den erfllten Wert zurck.

js
function resolveAfter2Seconds(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  const x = await resolveAfter2Seconds(10);
  console.log(x); // 10
}

f1();

Thenable Objekte

Thenable Objekte werden genauso aufgelst wie tatschliche Promise-Objekte.

js
async function f2() {
  const thenable = {
    then(resolve) {
      resolve("resolved!");
    },
  };
  console.log(await thenable); // "resolved!"
}

f2();

Sie knnen auch abgelehnt werden:

js
async function f2() {
  const thenable = {
    then(_, reject) {
      reject(new Error("rejected!"));
    },
  };
  await thenable; // Throws Error: rejected!
}

f2();

Umwandlung in Promise

Wenn der Wert kein Promise ist, wandelt await den Wert in ein aufgelstes Promise um und wartet auf es. Die Identitt des erwarteten Wertes ndert sich nicht, solange er keine then-Eigenschaft hat, die aufgerufen werden kann.

js
async function f3() {
  const y = await 20;
  console.log(y); // 20

  const obj = {};
  console.log((await obj) === obj); // true
}

f3();

Umgang mit abgelehnten Promises

Wenn das Promise abgelehnt wird, wird der abgelehnte Wert geworfen.

js
async function f4() {
  try {
    const z = await Promise.reject(new Error("rejected!"));
  } catch (e) {
    console.error(e); // Error: rejected!
  }
}

f4();

Sie knnen abgelehnte Promises ohne einen try-Block behandeln, indem Sie einen catch()-Handler vor dem Erwarten des Promises anhngen.

js
const response = await promisedFunction().catch((err) => {
  console.error(err);
  return "default response";
});
// response will be "default response" if the promise is rejected

Dies basiert auf der Annahme, dass promisedFunction() nie synchron einen Fehler wirft, sondern immer ein abgelehntes Promise zurckgibt. Dies ist bei den meisten richtig gestalteten promise-basierten Funktionen der Fall, die normalerweise wie folgt aussehen:

js
function promisedFunction() {
  // Immediately return a promise to minimize chance of an error being thrown
  return new Promise((resolve, reject) => {
    // do something async
  });
}

Wenn jedoch promisedFunction() einen Fehler synchron wirft, wird der Fehler nicht vom catch()-Handler erfasst. In diesem Fall ist die try...catch-Anweisung erforderlich.

Top-level await

Sie knnen das await-Schlsselwort eigenstndig (auerhalb einer async-Funktion) auf der obersten Ebene eines modul verwenden. Das bedeutet, dass Module mit Kindmodulen, die await verwenden, darauf warten, dass die Kindmodule ausgefhrt werden, bevor sie selbst ausgefhrt werden, ohne andere Kindmodule am Laden zu hindern.

Hier ist ein Beispiel fr ein Modul, das die Fetch API verwendet und await in der export-Anweisung spezifiziert. Alle Module, die dies einschlieen, warten darauf, dass der Fetch aufgelst wird, bevor sie irgendeinen Code ausfhren.

js
// fetch request
const colors = fetch("../data/colors.json").then((response) => response.json());

export default await colors;

Kontrollfluss-Effekte von await

Wenn in einem Code (entweder in einer async-Funktion oder in einem Modul) ein await auftritt, wird der erwartete Ausdruck ausgefhrt, whrend aller Code, der vom Wert des Ausdrucks abhngt, angehalten wird. Die Kontrolle verlsst die Funktion und kehrt zum Aufrufer zurck. Wenn der Wert des erwarteten Ausdrucks aufgelst ist, wird eine weitere Mikroaufgabe geplant, die den angehaltenen Code fortsetzt. Dies geschieht auch, wenn der erwartete Wert bereits ein aufgelstes Promise ist oder kein Promise ist: Die Ausfhrung kehrt nicht zur aktuellen Funktion zurck, bis alle bereits geplanten Mikroaufgaben verarbeitet sind. Zum Beispiel, betrachten Sie den folgenden Code:

js
async function foo(name) {
  console.log(name, "start");
  console.log(name, "middle");
  console.log(name, "end");
}

foo("First");
foo("Second");

// First start
// First middle
// First end
// Second start
// Second middle
// Second end

In diesem Fall ist die Funktion foo effektiv synchron, weil sie keinen await-Ausdruck enthlt. Die drei Anweisungen passieren im selben Tick. Daher fhren die beiden Funktionsaufrufe alle Anweisungen in Folge aus. In Promise-Begriffen entspricht die Funktion:

js
function foo(name) {
  return new Promise((resolve) => {
    console.log(name, "start");
    console.log(name, "middle");
    console.log(name, "end");
    resolve();
  });
}

Sobald es jedoch einen await gibt, wird die Funktion asynchron, und die Ausfhrung der folgenden Anweisungen wird auf den nchsten Tick verschoben.

js
async function foo(name) {
  console.log(name, "start");
  await console.log(name, "middle");
  console.log(name, "end");
}

foo("First");
foo("Second");

// First start
// First middle
// Second start
// Second middle
// First end
// Second end

Dies entspricht:

js
function foo(name) {
  return new Promise((resolve) => {
    console.log(name, "start");
    resolve(console.log(name, "middle"));
  }).then(() => {
    console.log(name, "end");
  });
}

Der zustzliche then()-Handler kann mit dem Executor kombiniert werden, der dem Konstruktor bergeben wird, da er nicht auf eine asynchrone Operation wartet. Sein Vorhandensein teilt jedoch den Code in eine zustzliche Mikroaufgabe fr jeden Aufruf von foo. Diese Mikroaufgaben werden geplant und in einer verschachtelten Weise ausgefhrt, was Ihren Code sowohl langsamer machen als auch unntige Race-Conditions einfhren kann. Stellen Sie daher sicher, await nur dann zu verwenden, wenn es notwendig ist (um Promises in ihre Werte zu entpacken).

Mikroaufgaben werden nicht nur durch die Promise-Auflsung, sondern auch durch andere Web-APIs geplant und sie werden mit derselben Prioritt ausgefhrt. Dieses Beispiel verwendet queueMicrotask(), um zu demonstrieren, wie die Mikroaufgaben-Warteschlange verarbeitet wird, wenn jeder await-Ausdruck auftritt.

js
let i = 0;

queueMicrotask(function test() {
  i++;
  console.log("microtask", i);
  if (i < 3) {
    queueMicrotask(test);
  }
});

(async () => {
  console.log("async function start");
  for (let i = 1; i < 3; i++) {
    await null;
    console.log("async function resume", i);
  }
  await null;
  console.log("async function end");
})();

queueMicrotask(() => {
  console.log("queueMicrotask() after calling async function");
});

console.log("script sync part end");

// Logs:
// async function start
// script sync part end
// microtask 1
// async function resume 1
// queueMicrotask() after calling async function
// microtask 2
// async function resume 2
// microtask 3
// async function end

In diesem Beispiel wird die test()-Funktion immer vor der Fortsetzung der async Funktion aufgerufen, sodass die Mikroaufgaben, die sie jeweils planen, immer in einer verschachtelten Weise ausgefhrt werden. Andererseits, da sowohl await als auch queueMicrotask() Mikroaufgaben planen, basiert die Ausfhrungsreihenfolge immer auf der Reihenfolge der Planung. Aus diesem Grund tritt die Protokollzeile "queueMicrotask() after calling async function" nach dem ersten Mal Fortsetzen der async Funktion auf.

Verbesserung des Stack-Traces

Manchmal wird await weggelassen, wenn ein Promise direkt von einer async-Funktion zurckgegeben wird.

js
async function noAwait() {
  // Some actions...

  return /* await */ lastAsyncTask();
}

Betrachten Sie jedoch den Fall, in dem lastAsyncTask asynchron einen Fehler wirft.

js
async function lastAsyncTask() {
  await null;
  throw new Error("failed");
}

async function noAwait() {
  return lastAsyncTask();
}

noAwait();

// Error: failed
//    at lastAsyncTask

Nur lastAsyncTask erscheint im Stack-Trace, da das Promise abgelehnt wurde, nachdem es bereits von noAwait zurckgegeben wurde in gewissem Sinne ist das Promise nicht mit noAwait verbunden. Um den Stack-Trace zu verbessern, knnen Sie await verwenden, um das Promise zu entpacken, sodass die Ausnahme in der aktuellen Funktion geworfen wird. Die Ausnahme wird dann sofort in ein neues abgelehntes Promise verpackt, aber whrend der Fehlererstellung wird der Aufrufer im Stack-Trace erscheinen.

js
async function lastAsyncTask() {
  await null;
  throw new Error("failed");
}

async function withAwait() {
  return await lastAsyncTask();
}

withAwait();

// Error: failed
//    at lastAsyncTask
//    at async withAwait

Im Gegensatz zu einem weit verbreiteten Glauben ist return await promise mindestens genauso schnell wie return promise, aufgrund der Optimierungen, die in der Spezifikation und den Engines zur Auflsung von nativen Promises vorgenommen werden. Es gibt einen Vorschlag, die Rckgabe von Promises zu beschleunigen, und Sie knnen auch ber V8s Optimierung von asynchronen Funktionen lesen. Daher ist return await auer aus stilistischen Grnden fast immer vorzuziehen.

Spezifikationen

Spezifikation
ECMAScript 2027 LanguageSpecification
# sec-async-function-definitions

Browser-Kompatibilitt

Siehe auch


Web Proxy Viewer  |  New URL  |  Original Page