Future/Promise ist ein asynchrones Programmiermuster, das einen Container für das Ergebnis einer noch nicht abgeschlossenen Operation darstellt. Laut Dart Documentation, 2025 ist Future ein schreibgeschütztes Ergebnis verzögerter Berechnungen, Promise ist ein schreibgeschützter Vertrag, der dieses Ergebnis füllt. Future wird in Dart, Java, Scala und C++ für then/catch-Ketten verwendet.
Wichtige Punkte
Future/Promise ist ein Paar miteinander verbundener Objekte, die ein asynchrones Ergebnis in zwei Rollen aufteilen. Promise kann das Ergebnis (resolve) oder einen Fehler (reject) schreiben. Future kann es nur lesen — durch Callbacks (then, catchError) oder durch await. Diese Trennung garantiert, dass der Konsument das Ergebnis nicht ändern, sondern nur verwenden kann.
Die Sprache Dart verwendet Future als ihren wichtigsten asynchronen Mechanismus. Future<T> ist ein Vertrag, in der Zukunft einen Wert vom Typ T zu erhalten. Ein Future kann sich in einem von drei Zuständen befinden: unresolved (Operation läuft), resolved with value (erfolgreich abgeschlossen) oder resolved with error (mit Fehler abgeschlossen). Einmal in den resolved-Zustand übergegangen, ändert sich das Future nie.
Promise in JavaScript ist analog zu Darts Future, aber mit einer reichhaltigeren API. Promise nimmt einen Executor entgegen — eine Funktion mit den Parametern resolve und reject. Die statischen Methoden Promise.all, Promise.race, Promise.allSettled ermöglichen das Kombinieren mehrerer Promises. Moderne Anwendungen verwenden die async/await-Syntax über Promise.
Future arbeitet auf Basis einer Event Loop — einem Ereigniszyklus, der asynchrone Operationen verarbeitet, ohne den Hauptthread zu blockieren. Wenn eine asynchrone Funktion aufgerufen wird (z. B. http.get), gibt sie sofort ein Future zurück. Die eigentliche Anfrage läuft im Hintergrund, während die Event Loop weiterhin andere Ereignisse verarbeitet. Nach Abschluss der Operation wechselt das Future in den resolved-Zustand und then wird aufgerufen.
Event Loop ist der Schlüsselmechanismus, auf dem Dart und JavaScript aufbauen. Die Event Loop verwaltet zwei Warteschlangen: die Microtask Queue (kurze Aufgaben, die vor dem nächsten Ereignis ausgeführt werden) und die Event Queue (IO-Ereignisse, Timer). Future.then platziert einen Callback in der Microtask Queue, Future.microtask — prioritäre Ausführung vor dem nächsten Frame.
Ketten von then() ermöglichen die sequenzielle Verarbeitung asynchroner Operationsergebnisse ohne Callback Hell. Jedes then() erhält das Ergebnis des vorherigen Schritts und gibt ein neues Future zurück. catchError() am Ende der Kette behandelt jeden Fehler, der in einem Schritt aufgetreten ist. Dies macht asynchronen Code linear und lesbar.
In Java erweitert CompletableFuture das Future/Promise-Konzept. Die Methode supplyAsync() startet eine asynchrone Aufgabe in ForkJoinPool.commonPool(). thenApply() transformiert das Ergebnis, thenCompose() entfaltet ein verschachteltes CompletableFuture. exceptionally() behandelt einen Fehler durch Rückgabe eines Standardwerts. allOf() und anyOf() funktionieren wie Promise.all und Promise.race in JavaScript. CompletableFuture unterstützt manuellen Abschluss über complete() und completeExceptionally() — dies ist analog zu Promise resolve/reject.
Promise ist ein Vertrag mit einem von drei Zuständen: pending (ausstehend), fulfilled (erfüllt) oder rejected (zurückgewiesen). Einmal in fulfilled oder rejected übergegangen, ändert sich das Promise nie — dies garantiert die Unveränderlichkeit des Ergebnisses für alle Konsumenten. Die Methode .then() wird asynchron aufgerufen, nachdem in einen abgeschlossenen Zustand übergegangen wurde.
Promise.all wartet auf den Abschluss aller übergebenen Promises und gibt ein Array von Ergebnissen in derselben Reihenfolge zurück. Wenn ein Promise mit einem Fehler fehlschlägt — wechselt das gesamte Promise.all zu rejected. Promise.race gibt das Ergebnis des ersten abgeschlossenen Promises zurück (Erfolg oder Fehler). Promise.allSettled wartet auf alle Promises unabhängig von Fehlern — gibt den Status jedes einzelnen zurück.
Verkettung ist der Hauptvorteil von Promise gegenüber Callbacks. Jedes .then() gibt ein neues Promise zurück, was Ketten beliebiger Länge ermöglicht. Ein Fehler in einem beliebigen Glied der Kette propagiert zum nächsten .catch(). Die Methode finally() führt Code nach Abschluss der Kette unabhängig vom Ergebnis aus — zur Ressourcenbereinigung.
Das erste Beispiel — Erstellen eines Future über eine async-Funktion und Behandlung mit then/catchError:
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 1))
return "Daten geladen"
}
fetchData()
.then((result) => print(result))
.catchError((error) => print("Fehler: $error"))
Das zweite Beispiel — Kombinieren mehrerer Futures mit Future.wait:
Future<List<String>> loadAll() async {
final futures = [
fetchFromApi("/users"),
fetchFromApi("/posts"),
fetchFromApi("/comments")
]
final results = await Future.wait(futures)
return results
}
Das dritte Beispiel — Promise in JavaScript mit manueller Erstellung und einer then-Kette:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Erledigt")
}, 1000)
})
promise
.then(value => console.log(value))
.catch(err => console.error(err))
Future/Promise unterscheidet sich vom Callback-Stil dadurch, dass es ein Vertragsobjekt zurückgibt, anstatt eine Callback-Funktion als Argument zu akzeptieren. Der Callback-Stil führt zu Verschachtelung (Callback Hell), während Future den Aufbau flacher then()-Ketten ermöglicht. Die async/await-Syntax macht Future-Code noch linearer und ähnelt synchronem Code.
Future repräsentiert genau ein asynchrones Ergebnis — eine Emission, nach der das Future abgeschlossen ist. Im Gegensatz zu Observable (Rx, ReactiveX) oder Flow (Kotlin Coroutines) unterstützt Future keine mehrfachen Werte im Zeitverlauf. Wenn Sie einen Ereignisstrom benötigen — verwenden Sie Stream in Dart, Observable in Rx oder Flow in Kotlin.
CompletableFuture in Java ist ein Analogon zu Promise mit einer erweiterten API: supplyAsync, thenApply, thenCompose, exceptionally. CompletableFuture ermöglicht das Kombinieren mehrerer asynchroner Operationen über allOf, anyOf und ermöglicht auch die Angabe eines benutzerdefinierten Executors für die Ausführung. Scala Future verwendet ExecutionContext zur Verwaltung des Thread-Pools und unterstützt die Komposition über for-comprehension.
In Dart unterscheidet sich das Future-Muster von JavaScript Promise dadurch, dass Dart eine strenge Typisierung hat: Future<String> garantiert den Typ des Rücckgabewerts. async-Funktionen in Dart müssen ein Future zurückgeben, und der Compiler prüft, dass alle Pfade einen korrekten Typ zurückgeben. Future.wait ist äquivalent zu Promise.all — es nimmt Iterable<Future<T>> entgegen und gibt Future<List<T>> zurück. Future.delayed und Future.error sind praktische Fabriken zum Testen asynchroner Szenarien.
Future/Promise ist in Python über concurrent.futures.Future und asyncio.Future implementiert. concurrent.futures.ThreadPoolExecutor.submit() gibt ein Future zurück, auf dem result() aufgerufen werden kann — ein blockierender Aufruf. asyncio.Future ist ein await-kompatibler Container für ein asynchrones Ergebnis in Asyncio. asyncio.gather() führt mehrere Coroutinen parallel aus und gibt eine Liste von Ergebnissen zurück, ähnlich wie Promise.all in JavaScript. Python verwendet auch callback-basiertes asyncio.ensure_future und add_done_callback-Ketten zur Zusammensetzung asynchroner Operationen, aber in modernem Code wird die async/await-Syntax mit asyncio.Task bevorzugt.
In der mobilen Entwicklung wird Future aktiv in Flutter-Anwendungen eingesetzt. Jede Netzwerkanfrage aus dem http- oder dio-Paket gibt ein Future zurück. FutureBuilder ist ein Widget, das ein Future und einen Snapshot-Status entgegennimmt: connectionDone, hasData, hasError. Beim Empfang von Daten enthält snapshot.data das Future-Ergebnis. StreamBuilder ist das Analogon für mehrere Werte. FutureBuilder eliminiert die manuelle Ladezustandsverwaltung über setState.
Scala Future verwendet implizit ExecutionContext — den Thread-Pool, auf dem die asynchrone Aufgabe ausgeführt wird. Die Komposition über map, flatMap, filter funktioniert, weil Future eine Monade ist. for-comprehension ermöglicht das sequenzielle Kombinieren mehrerer Futures ohne Verschachtelung: for { a <- futureA; b <- futureB } yield a + b. Future.sequence funktioniert wie Promise.all. Die Fehlerbehandlung wird über recover und recoverWith implementiert.
Future/Promise in C++ wird durch die Klassen std::future und std::promise aus der Bibliothek <future> repräsentiert. std::async startet eine asynchrone Funktion und gibt std::future zurück. std::promise ermöglicht das manuelle Setzen eines Werts über set_value() oder eines Fehlers über set_exception(). Im Gegensatz zu Dart und JavaScript blockiert std::future.get() den Thread, bis das Ergebnis empfangen wurde — dies ist ein wichtiger Unterschied, der beim Entwurf von Multithread-C++-Anwendungen zu berücksichtigen ist.
Beim Entwerfen von APIs, die Futures zurückgeben, befolgen Sie die Regel der einzigen Wahrheitsquelle: Jede asynchrone Anfrage wird einmal erstellt und über Future.memoize zwischengespeichert. Wenn zwei Komponenten dieselben Daten anfordern, erhalten sie dasselbe Future — dies verhindert doppelte Anfragen. Für Timeout verwenden Sie Future.timeout (Dart) oder Promise.race mit einem Timeout, um sicherzustellen, dass die asynchrone Operation innerhalb eines bestimmten Intervalls abgeschlossen wird.
Das Wiederholungsmuster (Retry) in Future wird über eine rekursive Kette implementiert: Bei einem Fehler in catch wird dieselbe asynchrone Funktion mit einer Verzögerung aufgerufen. Exponential Backoff erhöht das Intervall zwischen den Versuchen: 1 Sek — 2 Sek — 4 Sek — bis max. 30 Sek. In Dart wird dies in einer Erweiterung für Future gekapselt: future.retry(maxRetries: 3, delay: Duration(seconds: 1)). In Scala kombiniert Future.zip zwei unabhängige Ergebnisse in einem Tupel — eine Alternative zu Promise.all für zwei Futures. Die Stornierung wird bei Standard-Futures nicht unterstützt, aber über CancellationToken oder AbortController in JavaScript implementiert.
Häufig gestellte Fragen
Future ist ein schreibgeschützter Container zum Lesen eines asynchronen Ergebnisses über then oder await. Promise ist ein schreibgeschützter Vertrag, der einen Wert über resolve() annimmt und mit dem Future verknüpft. In Dart und JavaScript sind diese Konzepte kombiniert: Future/Promise ist eine Klasse. In Java und Scala sind sie getrennt.
Future repräsentiert ein einzelnes asynchrones Ergebnis — es emittiert genau einen Wert und schließt ab. Observable (Rx) emittiert mehrere Werte im Zeitverlauf — es ist ein asynchroner Strom. Wenn Sie eine HTTP-Antwort benötigen — verwenden Sie Future. Wenn Sie einen Strom von Datenbankänderungen benötigen — verwenden Sie Observable oder Stream.
async/await ist syntaktischer Zucker über Future/Promise. Das Schlüsselwort async markiert eine Funktion als asynchron — sie gibt ein Future zurück. await pausiert die Ausführung, bis das Future abgeschlossen ist, ohne den Thread zu blockieren. In Dart, JavaScript, Python und C# hat async/await die then-Ketten in den meisten Szenarien ersetzt.
Verwenden Sie in Dart .catchError() am Ende der Kette — es fängt Ausnahmen in jeder Phase ab. In JavaScript — .catch(). Dart verfügt auch über try/await/catch innerhalb von async-Funktionen. Verwenden Sie für die Fehlerbehandlung .catchError() mit einem Standardwert oder einem neuen Future.
Promise.all nimmt ein Array von Promises entgegen und gibt ein einzelnes Promise zurück, das mit einem Array von Ergebnissen aufgelöst wird. Alle Promises werden parallel ausgeführt — dies beschleunigt unabhängige Operationen (z. B. das Laden mehrerer Dateien). Wenn ein Promise abgelehnt wird — wird das gesamte Promise.all mit demselben Fehler abgelehnt.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch