Signatur
Beschreibung
Der Konstruktor new Promise(executor) erzeugt ein Promise, dessen Zustand (erfüllt oder abgelehnt) über die Funktionen resolve und reject gesteuert wird. Diese beiden Funktionen bekommt die übergebene Executor-Funktion als Argumente. Der Executor wird sofort und synchron während des Konstruktoraufrufs ausgeführt.
Der wichtigste Einsatzzweck ist das Promisifizieren älterer APIs, die mit Callbacks oder Events arbeiten, z. B. setTimeout, FileReader, XMLHttpRequest oder Node.js-Callbacks im Stil (err, result). Liefert eine Funktion bereits ein Promise (z. B. fetch()), brauchst du keinen eigenen Konstruktor, sondern verkettest direkt mit then() bzw. await.
Ein Promise lässt sich nur einmal festlegen: Weitere Aufrufe von resolve oder reject danach werden ignoriert. Wird resolve mit einem anderen Promise oder einem Thenable aufgerufen, übernimmt das neue Promise dessen Zustand. Wirft der Executor eine Ausnahme, wird das Promise automatisch abgelehnt – es sei denn, es wurde vorher schon festgelegt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $executor Pflicht | (resolve: (value?: any) => void, reject: (reason?: any) => void) => void | Funktion, die synchron vom Konstruktor aufgerufen wird. Sie erhält resolve (erfüllt das Promise mit einem Wert) und reject (lehnt das Promise mit einem Grund ab, idealerweise ein Error). Ihr Rückgabewert wird ignoriert. |
Rückgabewert
Promise-Objekt, das zunächst ausstehend (pending) ist und erfüllt bzw. abgelehnt wird, sobald resolve bzw. reject aufgerufen wird.Beispiele
setTimeout als Promise verpacken (sleep)
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const main = async () => {
console.log('Start');
await sleep(1000);
console.log('Eine Sekunde später');
};
main();
Node.js-Callback-API promisifizieren
import { readFile } from 'node:fs';
const readFileAsync = (path) =>
new Promise((resolve, reject) => {
readFile(path, 'utf8', (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
try {
const text = await readFileAsync('./config.json');
console.log(JSON.parse(text));
} catch (err) {
console.error('Fehler beim Lesen:', err.message);
}
Bild laden mit Event-Handlern
const loadImage = (src) =>
new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Bild konnte nicht geladen werden: ${src}`));
img.src = src;
});
loadImage('/logo.png')
.then((img) => console.log('Geladen:', img.naturalWidth, 'x', img.naturalHeight))
.catch((err) => console.error(err.message));
Executor läuft synchron, Festlegung nur einmal
const p = new Promise((resolve, reject) => {
console.log('Executor läuft');
resolve('erster Wert');
resolve('zweiter Wert'); // ignoriert
reject(new Error('zu spät')); // ignoriert
});
console.log('Nach dem Konstruktor');
p.then((v) => console.log('Ergebnis:', v));
// Wichtig · Fallstricke
- Nur mit
new:Promise()ohnenewwirft einenTypeError. Auch ein fehlender oder nicht aufrufbarer Executor führt zu einemTypeError. - Anti-Pattern „Promise-Konstruktor um ein Promise“:
new Promise((res, rej) => fetch(url).then(res, rej))ist überflüssig und fehleranfällig – gib einfachfetch(url)zurück. - Kein
async-Executor: Beinew Promise(async (resolve) => { ... })gehen Fehler nach dem erstenawaitverloren, da sie nicht zur Ablehnung des äußeren Promise führen. - Asynchrone Ausnahmen werden nicht abgefangen: Ein
throwinnerhalb einessetTimeout-Callbacks im Executor lehnt das Promise nicht ab – dort explizitreject()aufrufen. - Nach
resolve/rejectläuft der Code weiter: Mitreturnabbrechen, wenn danach nichts mehr passieren soll. - Mit
Error-Objekten ablehnen, damit ein Stacktrace erhalten bleibt. Nicht behandelte Ablehnungen lösenunhandledrejection(Browser) bzw. in Node.js 15+ standardmäßig einen Prozessabbruch aus. - Für Node.js-Callbacks gibt es alternativ
util.promisify(); seit ES2024 liefertPromise.withResolvers()resolve/rejectaußerhalb eines Executors. - Kompatibilität: in allen modernen Browsern und Node.js unterstützt, nicht im Internet Explorer (Polyfill nötig).