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

Promise - 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

Promise

Baseline Weitgehend verfgbar *

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

* Einige Teile dieser Funktion werden mglicherweise unterschiedlich gut untersttzt.

Das Promise-Objekt reprsentiert den Abschluss (oder das Scheitern) einer asynchronen Operation und dessen resultierenden Wert.

Um zu erfahren, wie Promises funktionieren und wie Sie sie verwenden knnen, empfehlen wir Ihnen, zunchst Using promises zu lesen.

In diesem Artikel

Beschreibung

Ein Promise ist ein Platzhalter fr einen Wert, der mglicherweise noch nicht bekannt ist, wenn das Promise erstellt wird. Es ermglicht Ihnen, Handler mit dem erfolgreichen Wert oder dem Grund des Scheiterns einer asynchronen Aktion zu verknpfen. Dies lsst asynchrone Methoden Werte zurckgeben wie synchrone Methoden: Anstatt den endgltigen Wert direkt zurckzugeben, gibt die asynchrone Methode ein Promise zurck, das verspricht, den Wert irgendwann in der Zukunft bereitzustellen.

Ein Promise befindet sich in einem der folgenden Zustnde:

  • pending: Anfangszustand, weder erfllt noch abgelehnt.
  • fulfilled: Bedeutet, dass die Operation erfolgreich abgeschlossen wurde.
  • rejected: Bedeutet, dass die Operation fehlgeschlagen ist.

Der endgltige Zustand eines schwebenden Promises kann entweder fulfilled mit einem Wert oder rejected mit einem Grund (Fehler) sein. Wenn eine dieser Optionen eintritt, werden die mit der then-Methode des Promises verbundenen Handler aufgerufen. Wenn das Promise bereits erfllt oder abgelehnt wurde, wenn ein entsprechender Handler angehngt wird, wird der Handler dennoch aufgerufen. Es gibt also keinen Wettlauf zwischen dem Abschluss einer asynchronen Operation und dem Anfgen ihrer Handler.

Ein Promise gilt als settled, wenn es entweder erfllt oder abgelehnt ist, aber nicht mehr schwebend.

Flussdiagramm, das zeigt, wie die Promise-Zustnde zwischen schwebend, erfllt und abgelehnt ber dann/catch-Handler wechseln. Ein schwebendes Promise kann entweder erfllt oder abgelehnt werden. Wenn es erfllt wird, wird der "bei Erfllung"-Handler oder das erste Argument der then()-Methode ausgefhrt und fhrt weitere asynchrone Aktionen aus. Wenn es abgelehnt wird, wird der Fehler-Handler entweder als zweites Argument der then()-Methode oder als einziges Argument der catch()-Methode ausgefhrt. [Flussdiagramm, das zeigt, wie die Promise-Zustnde zwischen schwebend, erfllt und abgelehnt ber dann/catch-Handler wechseln. Ein schwebendes Promise kann entweder erfllt oder abgelehnt werden. Wenn es erfllt wird, wird der "bei Erfllung"-Handler oder das erste Argument der then()-Methode ausgefhrt und fhrt weitere asynchrone Aktionen aus. Wenn es abgelehnt wird, wird der Fehler-Handler entweder als zweites Argument der then()-Methode oder als einziges Argument der catch()-Methode ausgefhrt.]

Sie werden auch den Begriff resolved in Verbindung mit Promises hren dies bedeutet, dass das Promise sich im Zustand "settled" befindet oder "festgelegt" ist, um den endgltigen Zustand eines anderen Promises wiederzugeben, und eine weitere Lsung oder Ablehnung keinen Effekt mehr hat. Das Dokument States and fates aus dem ursprnglichen Promise-Vorschlag enthlt weitere Details zur Terminologie der Promises. Umgnglich sind "resolved" Promises oft gleichbedeutend mit "fulfilled" Promises, aber wie im Abschnitt "States and fates" dargestellt, knnen resolved Promises auch schwebend oder abgelehnt sein. Zum Beispiel:

js
new Promise((resolveOuter) => {
  resolveOuter(
    new Promise((resolveInner) => {
      setTimeout(resolveInner, 1000);
    }),
  );
});

Dieses Promise ist bereits resolved, wenn es erstellt wird (weil resolveOuter synchron aufgerufen wird), aber es ist mit einem anderen Promise resolved und wird daher erst eine Sekunde spter fulfilled, wenn das innere Promise erfllt wird. In der Praxis geschieht die "Resolution" oft hinter den Kulissen und ist nicht sichtbar, und nur seine Erfllung oder Ablehnung sind sichtbar.

Hinweis: Einige andere Sprachen haben Mechanismen zur verzgerten Auswertung und Verschiebung einer Berechnung, die sie ebenfalls "Promises" nennen, z. B. Scheme. Promises in JavaScript reprsentieren bereits laufende Prozesse, die mit Callback-Funktionen verkettet werden knnen. Wenn Sie einen Ausdruck verzgert auswerten mchten, sollten Sie eine Funktion ohne Argumente in Betracht ziehen, z. B. f = () => expression, um den verzgert ausgewerteten Ausdruck zu erstellen, und f(), um den Ausdruck sofort auszuwerten.

Promise selbst verfgt ber kein erstklassiges Protokoll zur Stornierung, aber Sie knnen mglicherweise direkt die zugrunde liegende asynchrone Operation abbrechen, normalerweise mit AbortController.

Verkettete Promises

Die Promise-Methoden then(), catch() und finally() werden verwendet, um eine weitere Aktion mit einem settled Promise zu verknpfen. Die then()-Methode nimmt bis zu zwei Argumente an; das erste Argument ist eine Callback-Funktion fr den Fall, dass das Promise erfllt wird, und das zweite Argument ist eine Callback-Funktion fr den Fall, dass das Promise abgelehnt wird. Die catch()- und finally()-Methoden rufen intern then() auf und machen die Fehlerbehandlung weniger ausfhrlich. Zum Beispiel ist ein catch() im Grunde nur ein then() ohne den Erfllungs-Handler zu bergeben. Da diese Methoden Promises zurckgeben, knnen sie verkettet werden. Zum Beispiel:

js
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 300);
});

myPromise
  .then(handleFulfilledA, handleRejectedA)
  .then(handleFulfilledB, handleRejectedB)
  .then(handleFulfilledC, handleRejectedC);

Wir verwenden die folgende Terminologie: initiales Promise ist das Promise, auf dem then aufgerufen wird; neues Promise ist das von then zurckgegebene Promise. Die beiden an then bergebenen Callbacks werden als Erfllungs-Handler bzw. Ablehnungs-Handler bezeichnet.

Der settled Zustand des initialen Promises bestimmt, welcher Handler ausgefhrt wird.

  • Wenn das initiale Promise erfllt ist, wird der Erfllungs-Handler mit dem Erfllungswert aufgerufen.
  • Wenn das initiale Promise abgelehnt ist, wird der Ablehnungs-Handler mit dem Grund der Ablehnung aufgerufen.

Der Abschluss des Handlers bestimmt den settled Zustand des neuen Promises.

  • Wenn der Handler einen thenable Wert zurckgibt, setzt sich das neue Promise im selben Zustand wie der zurckgegebene Wert.
  • Wenn der Handler einen nicht-thenable Wert zurckgibt, wird das neue Promise mit dem zurckgegebenen Wert erfllt.
  • Wenn der Handler einen Fehler auslst, wird das neue Promise mit dem ausgelsten Fehler abgelehnt.
  • Wenn das initiale Promise keinen entsprechenden Handler angehngt hat, wird das neue Promise denselben Zustand wie das initiale Promise annehmen das heit, ohne einen Ablehnungs-Handler bleibt ein abgelehntes Promise mit demselben Grund abgelehnt.

Zum Beispiel wird im obigen Code, wenn myPromise abgelehnt wird, handleRejectedA aufgerufen, und wenn handleRejectedA normal (ohne Auslsen oder Zurckgeben eines abgelehnten Promises) abgeschlossen wird, wird das Promise, das durch das erste then zurckgegeben wird, erfllt, anstatt abgelehnt zu bleiben. Wenn ein Fehler sofort gehandhabt werden muss, aber der Fehlerzustand in der Kette beibehalten werden soll, muss im Ablehnungs-Handler ein Fehler irgendeiner Art ausgelst werden. Andererseits knnen wir bei fehlendem sofortigen Bedarf die Fehlerbehandlung bis zum finalen catch()-Handler aufschieben.

js
myPromise
  .then(handleFulfilledA)
  .then(handleFulfilledB)
  .then(handleFulfilledC)
  .catch(handleRejectedAny);

Wenn Sie Pfeilfunktionen fr die Callback-Funktionen verwenden, knnte die Implementierung der Promise-Kette etwa so aussehen:

js
myPromise
  .then((value) => `${value} and bar`)
  .then((value) => `${value} and bar again`)
  .then((value) => `${value} and again`)
  .then((value) => `${value} and again`)
  .then((value) => {
    console.log(value);
  })
  .catch((err) => {
    console.error(err);
  });

Hinweis: Fr eine schnellere Ausfhrung sollten alle synchronen Aktionen vorzugsweise innerhalb eines Handlers durchgefhrt werden, andernfalls wrde es mehrere Ticks dauern, um alle Handler in Folge auszufhren.

JavaScript pflegt eine Aufgaben-Warteschlange. Jedes Mal whlt JavaScript eine Aufgabe aus der Warteschlange aus und fhrt sie vollstndig aus. Die Aufgaben werden vom Executor des Promise()-Konstruktors, den an then bergebenen Handlern oder einer beliebigen Plattform-API definiert, die ein Promise zurckgibt. Die Promises in einer Kette reprsentieren die Abhngigkeitsbeziehung zwischen diesen Aufgaben. Wenn ein Promise erfllt wird, werden die jeweiligen damit verbundenen Handler an das Ende der Aufgaben-Warteschlange angehngt.

Ein Promise kann an mehr als einer Kette teilnehmen. Im folgenden Code bewirkt die Erfllung von promiseA, dass sowohl handleFulfilled1 als auch handleFulfilled2 zur Aufgaben-Warteschlange hinzugefgt werden. Da handleFulfilled1 zuerst registriert ist, wird es zuerst ausgefhrt.

js
const promiseA = new Promise(myExecutorFunc);
const promiseB = promiseA.then(handleFulfilled1, handleRejected1);
const promiseC = promiseA.then(handleFulfilled2, handleRejected2);

Eine Aktion kann einem bereits erfllten Promise zugewiesen werden. In diesem Fall wird die Aktion sofort an das Ende der Aufgaben-Warteschlange angehngt und wird ausgefhrt, wenn alle bestehenden Aufgaben abgeschlossen sind. Daher tritt eine Aktion fr ein bereits "erledigtes" Promise erst auf, nachdem der aktuelle synchrone Code abgeschlossen ist und mindestens ein Schleifen-Tick vergangen ist. Dies garantiert, dass Promise-Aktionen asynchron sind.

js
const promiseA = new Promise((resolve, reject) => {
  resolve(777);
});
// At this point, "promiseA" is already settled.
promiseA.then((val) => console.log("asynchronous logging has val:", val));
console.log("immediate logging");

// produces output in this order:
// immediate logging
// asynchronous logging has val: 777

Thenables

Das JavaScript-kosystem hatte viele Promise-Implementierungen, lange bevor es Teil der Sprache wurde. Trotz interner Unterschiede implementieren alle Promise-hnlichen Objekte mindestens die Thenable-Schnittstelle. Ein Thenable implementiert die .then() Methode, die mit zwei Callbacks aufgerufen wird: eines fr den Fall, dass das Promise erfllt wird, und eines fr den Fall, dass es abgelehnt wird. Promises sind ebenfalls Thenables.

Um mit vorhandenen Promise-Implementierungen interoperieren zu knnen, erlaubt die Sprache die Verwendung von Thenables anstelle von Promises. Zum Beispiel wird Promise.resolve nicht nur Promises auflsen, sondern auch Thenables verfolgen.

js
// This is not a Promises/A+ compliant thenable! It calls onFulfilled
// synchronously. For demonstration only.
const thenable = {
  then(onFulfilled, onRejected) {
    onFulfilled({
      // The thenable is fulfilled with another thenable
      then(onFulfilled, onRejected) {
        onFulfilled(42);
      },
    });
  },
};

Promise.resolve(thenable); // A promise fulfilled with 42

Die then()-Methode ist verantwortlich fr die Planung der Ausfhrung der bereitgestellten onFulfilled- und onRejected-Callbacks. Ihre Semantik, einschlielich Fehlerbehandlung und Asynchronitt, ist in der Promises/A+ Spezifikation genau definiert, und wir werden sie hier nicht wiederholen. Es ist sehr selten, dass Sie selbst ein Thenable implementieren mssen; selbst wenn Sie keine nativen Promises verwenden, wrden Sie wahrscheinlich eine Promise-Bibliothek wie Bluebird verwenden.

Promise-Konkurrenz

Die Promise-Klasse bietet vier statische Methoden, um die gleichzeitige Bearbeitung asynchroner Aufgaben zu erleichtern:

Promise.all()

Erfllt sich, wenn alle der Promises erfllt sind; lehnt ab, wenn irgendeines der Promises abgelehnt wird.

Promise.allSettled()

Erfllt sich, wenn alle Promises erledigt sind.

Promise.any()

Erfllt sich, wenn irgendeines der Promises erfllt wird; lehnt ab, wenn alle der Promises abgelehnt werden.

Promise.race()

Erledigt sich, wenn irgendeines der Promises erledigt ist. Mit anderen Worten, erfllt sich, wenn irgendeines der Promises erfllt wird; lehnt ab, wenn irgendeines der Promises abgelehnt wird.

Alle diese Methoden nehmen ein iterierbares Objekt von Promises (Thenables, um genau zu sein) und geben ein neues Promise zurck. Sie untersttzen alle Subklassierung, was bedeutet, dass sie auf Unterklassen von Promise aufgerufen werden knnen, und das Ergebnis wird ein Promise des Unterklassentyps sein. Dazu muss der Konstruktor der Unterklasse dieselbe Signatur wie der des Promise() Konstruktors implementieren eine einzelne executor-Funktion, die mit den resolve- und reject-Callbacks als Parameter aufgerufen werden kann, akzeptieren. Die Unterklasse muss auch eine statische resolve-Methode haben, die wie Promise.resolve() aufgerufen werden kann, um Werte zu Promises aufzulsen.

Beachten Sie, dass JavaScript von Natur aus einzelstrngig ist, so dass zu einem gegebenen Zeitpunkt nur eine Aufgabe ausgefhrt wird, obwohl die Kontrolle zwischen verschiedenen Promises wechseln kann, was die Ausfhrung der Promises scheinbar gleichzeitig erscheinen lsst. Parallele Ausfhrung in JavaScript kann nur durch Worker-Threads erreicht werden.

Konstruktor

Promise()

Erstellt ein neues Promise-Objekt. Der Konstruktor wird hauptschlich verwendet, um Funktionen zu ummanteln, die nicht bereits Promises untersttzen.

Statische Eigenschaften

Promise[Symbol.species]

Gibt den Konstruktor zurck, der verwendet wird, um Rckgabewerte von Promise-Methoden zu konstruieren.

Statische Methoden

Promise.all()

Nimmt ein iterierbares Objekt von Promises als Eingabe an und gibt ein einzelnes Promise zurck. Dieses zurckgegebene Promise erfllt sich, wenn alle Promises der Eingabe erfllt sind (einschlielich wenn ein leeres iterierbares Objekt bergeben wird), mit einem Array der Erfllungswerte. Es wird abgelehnt, wenn eines der eingereichten Promises abgelehnt wird, mit diesem ersten Ablehnungsgrund.

Promise.allSettled()

Nimmt ein iterierbares Objekt von Promises als Eingabe an und gibt ein einzelnes Promise zurck. Dieses zurckgegebene Promise erfllt sich, wenn alle der eingereichten Promises erledigt sind (einschlielich wenn ein leeres iterierbares Objekt bergeben wird), mit einem Array von Objekten, die das Ergebnis jedes einzelnen Promises beschreiben.

Promise.any()

Nimmt ein iterierbares Objekt von Promises als Eingabe an und gibt ein einzelnes Promise zurck. Dieses zurckgegebene Promise erfllt sich, wenn eines der eingereichten Promises erfllt wird, mit diesem ersten Erfllungswert. Es lehnt ab, wenn alle der eingereichten Promises abgelehnt werden (einschlielich wenn ein leeres iterierbares Objekt bergeben wird), mit einem AggregateError, der ein Array von Ablehnungsgrnden enthlt.

Promise.race()

Nimmt ein iterierbares Objekt von Promises als Eingabe an und gibt ein einzelnes Promise zurck. Dieses zurckgegebene Promise wird mit dem endgltigen Zustand des ersten erfllten Promises abgewickelt.

Promise.reject()

Gibt ein neues Promise-Objekt zurck, das mit dem angegebenen Grund abgelehnt wird.

Promise.resolve()

Gibt ein Promise-Objekt zurck, das mit dem angegebenen Wert aufgelst wurde. Wenn der Wert ein Thenable ist (d.h. eine then-Methode hat), wird das zurckgegebene Promise diesem Thenable "folgen" und dessen endgltigen Zustand annehmen; ansonsten wird das zurckgegebene Promise mit dem Wert erfllt.

Promise.try()

Nimmt eine Callback-Funktion jeglicher Art (gibt zurck oder lst Fehler aus, synchron oder asynchron) und ummantelt deren Ergebnis in einem Promise.

Promise.withResolvers()

Gibt ein Objekt zurck, das ein neues Promise-Objekt und zwei Funktionen enthlt, um es zu erfllen oder abzulehnen, entsprechend den zwei Parametern, die an den Executor des Promise()-Konstruktors bergeben werden.

Instanzeigenschaften

Diese Eigenschaften sind auf Promise.prototype definiert und werden von allen Promise-Instanzen geteilt.

Promise.prototype.constructor

Die Konstruktorfunktion, die das Instanzobjekt erstellt hat. Bei Promise-Instanzen ist der Anfangswert der Promise-Konstruktor.

Promise.prototype[Symbol.toStringTag]

Der Anfangswert der [Symbol.toStringTag]-Eigenschaft ist der String "Promise". Diese Eigenschaft wird in Object.prototype.toString() verwendet.

Instanzmethoden

Promise.prototype.catch()

Fgt einen Ablehnungs-Handler-Callback zum Promise hinzu und gibt ein neues Promise zurck, das sich auf den Rckgabewert des Callbacks auflst, wenn es aufgerufen wird, oder auf seinen ursprnglichen Erfllungswert, wenn das Promise stattdessen erfllt wurde.

Promise.prototype.finally()

Fgt einen Handler zum Promise hinzu und gibt ein neues Promise zurck, das aufgelst wird, wenn das ursprngliche Promise aufgelst wird. Der Handler wird aufgerufen, wenn das Promise gefestigt ist, unabhngig davon, ob erfllt oder abgelehnt.

Promise.prototype.then()

Fgt Erfllungs- und Ablehnungs-Handler zum Promise hinzu und gibt ein neues Promise zurck, das sich auf den Rckgabewert des aufgerufenen Handlers auflst, oder auf seinen ursprnglichen gefestigten Wert, wenn das Promise nicht behandelt wurde (d.h. wenn der relevante Handler onFulfilled oder onRejected keine Funktion ist).

Beispiele

Einfaches Beispiel

In diesem Beispiel verwenden wir setTimeout(...), um asynchronen Code zu simulieren. Tatschlich werden Sie wahrscheinlich etwas wie XHR oder eine HTML-API verwenden.

js
const myFirstPromise = new Promise((resolve, reject) => {
  // We call resolve(...) when what we were doing asynchronously
  // was successful, and reject(...) when it failed.
  setTimeout(() => {
    resolve("Success!"); // Yay! Everything went well!
  }, 250);
});

myFirstPromise.then((successMessage) => {
  // successMessage is whatever we passed in the resolve(...) function above.
  // It doesn't have to be a string, but if it is only a succeed message, it probably will be.
  console.log(`Yay! ${successMessage}`);
});

Beispiel mit diversen Situationen

Dieses Beispiel zeigt diverse Techniken zur Nutzung der Promise-Fhigkeiten und verschiedene Situationen, die auftreten knnen. Um dies zu verstehen, scrollen Sie zunchst ans Ende des Codeblocks und betrachten Sie die Promise-Kette. Nach Bereitstellung eines anfnglichen Promises kann eine Kette von Promises folgen. Die Kette besteht aus .then()-Aufrufen und hat typischerweise (aber nicht notwendigerweise) ein einzelnes .catch() am Ende, optional gefolgt von .finally(). In diesem Beispiel wird die Promise-Kette durch ein kundenspezifisch geschriebenes new Promise() Konstrukt initiiert; in der Praxis beginnen Promise-Ketten jedoch eher mit einer API-Funktion (von jemand anderem geschrieben), die ein Promise zurckgibt.

Die Beispielsunktion tetheredGetNumber() zeigt, dass ein Promise-Generator reject() verwenden wird, whrend er einen asynchronen Aufruf einrichtet oder innerhalb des Callbacks oder beides. Die Funktion promiseGetWord() veranschaulicht, wie eine API-Funktion ein Promise auf selbstndige Weise generieren und zurckgeben knnte.

Beachten Sie, dass die Funktion troubleWithGetNumber() mit einem throw endet. Das ist erzwungen, weil eine Promise-Kette durch alle .then() Promises geht, selbst nach einem Fehler, und ohne das throw wrde der Fehler scheinbar "behoben" aussehen. Das ist eine Umstndlichkeit, und aus diesem Grund wird onRejected hufig in der gesamten Kette von .then()-Promises weggelassen, und es gibt nur ein einziges onRejected im finalen catch().

Dieser Code kann unter NodeJS ausgefhrt werden. Das Verstndnis wird durch die tatschliche Beobachtung der Fehler verstrkt. Um mehr Fehler zu erzwingen, ndern Sie die threshold-Werte.

js
// To experiment with error handling, "threshold" values cause errors randomly
const THRESHOLD_A = 8; // can use zero 0 to guarantee error

function tetheredGetNumber(resolve, reject) {
  setTimeout(() => {
    const randomInt = Date.now();
    const value = randomInt % 10;
    if (value < THRESHOLD_A) {
      resolve(value);
    } else {
      reject(new RangeError(`Too large: ${value}`));
    }
  }, 500);
}

function determineParity(value) {
  const isOdd = value % 2 === 1;
  return { value, isOdd };
}

function troubleWithGetNumber(reason) {
  const err = new Error("Trouble getting number", { cause: reason });
  console.error(err);
  throw err;
}

function promiseGetWord(parityInfo) {
  return new Promise((resolve, reject) => {
    const { value, isOdd } = parityInfo;
    if (value >= THRESHOLD_A - 1) {
      reject(new RangeError(`Still too large: ${value}`));
    } else {
      parityInfo.wordEvenOdd = isOdd ? "odd" : "even";
      resolve(parityInfo);
    }
  });
}

new Promise(tetheredGetNumber)
  .then(determineParity, troubleWithGetNumber)
  .then(promiseGetWord)
  .then((info) => {
    console.log(`Got: ${info.value}, ${info.wordEvenOdd}`);
    return info;
  })
  .catch((reason) => {
    if (reason.cause) {
      console.error("Had previously handled error");
    } else {
      console.error(`Trouble with promiseGetWord(): ${reason}`);
    }
  })
  .finally((info) => console.log("All done"));

Fortgeschrittenes Beispiel

Dieses kleine Beispiel zeigt den Mechanismus eines Promise. Die testPromise()-Methode wird jedes Mal aufgerufen, wenn der <button> geklickt wird. Sie erstellt ein Promise, das durch Verwendung von setTimeout() mit der Promise-Zhlung (Zahl startend bei 1) alle 1-3 Sekunden zufllig erfllt wird. Der Promise()-Konstruktor wird verwendet, um das Promise zu erstellen.

Die Erfllung des Promises wird ber einen Erfllungs-Callback, der mit p1.then() gesetzt wird, protokolliert. Einige Protokolle zeigen, wie der synchrone Teil der Methode vom asynchronen Abschluss des Promises entkoppelt ist.

Indem Sie den Button mehrmals in kurzer Zeit klicken, knnen Sie sogar beobachten, wie die verschiedenen Promises nacheinander erfllt werden.

HTML

html
<button id="make-promise">Make a promise!</button>
<div id="log"></div>

JavaScript

js
"use strict";

let promiseCount = 0;

function testPromise() {
  const thisPromiseCount = ++promiseCount;
  const log = document.getElementById("log");
  // begin
  log.insertAdjacentHTML("beforeend", `${thisPromiseCount}) Started<br>`);
  // We make a new promise: we promise a numeric count of this promise,
  // starting from 1 (after waiting 3s)
  const p1 = new Promise((resolve, reject) => {
    // The executor function is called with the ability
    // to resolve or reject the promise
    log.insertAdjacentHTML(
      "beforeend",
      `${thisPromiseCount}) Promise constructor<br>`,
    );
    // This is only an example to create asynchronism
    setTimeout(
      () => {
        // We fulfill the promise
        resolve(thisPromiseCount);
      },
      Math.random() * 2000 + 1000,
    );
  });

  // We define what to do when the promise is resolved with the then() call,
  // and what to do when the promise is rejected with the catch() call
  p1.then((val) => {
    // Log the fulfillment value
    log.insertAdjacentHTML("beforeend", `${val}) Promise fulfilled<br>`);
  }).catch((reason) => {
    // Log the rejection reason
    console.log(`Handle rejected promise (${reason}) here.`);
  });
  // end
  log.insertAdjacentHTML("beforeend", `${thisPromiseCount}) Promise made<br>`);
}

const btn = document.getElementById("make-promise");
btn.addEventListener("click", testPromise);

Ergebnis

Laden eines Bildes mit XHR

Ein weiteres Beispiel mit Promise und XMLHttpRequest, um ein Bild zu laden, wird unten gezeigt. Jeder Schritt ist kommentiert und ermglicht es Ihnen, die Architektur von Promise und XHR genau zu verfolgen.

js
function imgLoad(url) {
  // Create new promise with the Promise() constructor;
  // This has as its argument a function with two parameters, resolve and reject
  return new Promise((resolve, reject) => {
    // XHR to load an image
    const request = new XMLHttpRequest();
    request.open("GET", url);
    request.responseType = "blob";
    // When the request loads, check whether it was successful
    request.onload = () => {
      if (request.status === 200) {
        // If successful, resolve the promise by passing back the request response
        resolve(request.response);
      } else {
        // If it fails, reject the promise with an error message
        reject(
          Error(
            `Image didn't load successfully; error code: + ${request.statusText}`,
          ),
        );
      }
    };
    // Handle network errors
    request.onerror = () => reject(new Error("There was a network error."));
    // Send the request
    request.send();
  });
}

// Get a reference to the body element, and create a new image object
const body = document.querySelector("body");
const myImage = new Image();
const imgUrl =
  "https://mdn.github.io/shared-assets/images/examples/round-balloon.png";

// Call the function with the URL we want to load, then chain the
// promise then() method with two callbacks
imgLoad(imgUrl).then(
  (response) => {
    // The first runs when the promise resolves, with the request.response
    // specified within the resolve() method.
    const imageURL = URL.createObjectURL(response);
    myImage.src = imageURL;
    body.appendChild(myImage);
  },
  (error) => {
    // The second runs when the promise
    // is rejected, and logs the Error specified with the reject() method.
    console.log(error);
  },
);

Verfolgung des zustndigen Einstellungsobjekts

Ein Einstellungsobjekt ist eine Umgebung, die zustzliche Informationen bereitstellt, wenn JavaScript-Code ausgefhrt wird. Dies beinhaltet den Realm und die Modul-Karte sowie HTML-spezifische Informationen wie den Ursprung. Das zustndige Einstellungsobjekt wird verfolgt, um sicherzustellen, dass der Browser wei, welches fr ein bestimmtes Stck Benutzercode zu verwenden ist.

Um sich dies besser vorzustellen, knnen wir uns ansehen, wie der Realm ein Problem darstellen knnte. Ein Realm kann grob als das globale Objekt betrachtet werden. Was Reiche einzigartig macht, ist, dass sie alle notwendigen Informationen zur Ausfhrung von JavaScript-Code enthalten. Dazu gehren Objekte wie Array und Error. Jedes Einstellungsobjekt hat seine eigene "Kopie" dieser und sie werden nicht geteilt. Das kann unerwartetes Verhalten in Bezug auf Promises verursachen. Um dies zu umgehen, verfolgen wir etwas, das das zustndige Einstellungsobjekt genannt wird. Dies stellt Informationen dar, die spezifisch fr den Kontext des Benutzercodes sind, der fr einen bestimmten Funktionsaufruf verantwortlich ist.

Um dies weiter zu veranschaulichen, knnen wir uns ansehen, wie ein in ein Dokument eingebettetes <iframe> mit seinem Host kommuniziert. Da alle Web-APIs sich des zustndigen Einstellungsobjekts bewusst sind, funktioniert Folgendes in allen Browsern:

html
<!doctype html>
<iframe></iframe>
<!-- we have a realm here -->
<script>
  // we have a realm here as well
  const bound = frames[0].postMessage.bind(frames[0], "some data", "*");
  // bound is a built-in function  there is no user
  // code on the stack, so which realm do we use?
  setTimeout(bound);
  // this still works, because we use the youngest
  // realm (the incumbent) on the stack
</script>

Das gleiche Konzept gilt fr Promises. Wenn wir das obige Beispiel ein wenig ndern, erhalten wir Folgendes:

html
<!doctype html>
<iframe></iframe>
<!-- we have a realm here -->
<script>
  // we have a realm here as well
  const bound = frames[0].postMessage.bind(frames[0], "some data", "*");
  // bound is a built in function  there is no user
  // code on the stack  which realm do we use?
  Promise.resolve(undefined).then(bound);
  // this still works, because we use the youngest
  // realm (the incumbent) on the stack
</script>

Wenn wir dies ndern, so dass das <iframe> im Dokument auf Post-Nachrichten wartet, knnen wir den Effekt des zustndigen Einstellungsobjekts beobachten:

html
<!-- y.html -->
<!doctype html>
<iframe src="x.html"></iframe>
<script>
  const bound = frames[0].postMessage.bind(frames[0], "some data", "*");
  Promise.resolve(undefined).then(bound);
</script>
html
<!-- x.html -->
<!doctype html>
<script>
  window.addEventListener("message", (event) => {
    document.querySelector("#text").textContent = "hello";
    // this code will only run in browsers that track the incumbent settings object
    console.log(event);
  });
</script>

Im obigen Beispiel wird der innere Text des <iframe> nur aktualisiert, wenn das zustndige Einstellungsobjekt verfolgt wird. Das liegt daran, dass wir ohne Verfolgung des Zustndigen am Ende die falsche Umgebung verwenden knnten, um die Nachricht zu senden.

Hinweis: Derzeit ist die Verfolgung des zustndigen Realm vollstndig in Firefox implementiert und hat teilweise Implementierungen in Chrome und Safari.

Spezifikationen

Spezifikation
ECMAScript 2027 LanguageSpecification
# sec-promise-objects

Browser-Kompatibilitt

Siehe auch


Web Proxy Viewer  |  New URL  |  Original Page