Future/Promise is een patroon voor asynchroon programmeren dat een container biedt voor het resultaat van een nog niet voltooide bewerking. Volgens Dart Documentation, 2025 is Future een read-only resultaat van uitgestelde berekeningen, Promise een write-only contract dat dit resultaat invult. Future wordt gebruikt in Dart, Java, Scala en C++ voor then/catch-ketens.
Belangrijkste punten
Future/Promise is een paar onderling verbonden objecten die het asynchrone resultaat verdelen over twee rollen. Promise kan het resultaat (resolve) of de fout (reject) schrijven. Future kan het alleen lezen — via callback (then, catchError) of via await. Deze scheiding garandeert dat de consument het resultaat niet kan wijzigen, maar alleen kan gebruiken.
De taal Dart gebruikt Future als het belangrijkste asynchrone mechanisme. Future<T> is een contract voor het ontvangen van een waarde van type T in de toekomst. Future kan in een van drie toestanden verkeren: unresolved (bewerking wordt uitgevoerd), resolved with value (succesvol voltooid) of resolved with error (voltooid met fout). Na overgang naar de resolved-toestand verandert Future niet.
Promise in JavaScript is de analoog van Dart's Future, maar met een rijker API. Promise ontvangt een executor — een functie met parameters resolve en reject. Statische methoden Promise.all, Promise.race, Promise.allSettled maken het mogelijk meerdere promises te combineren. Moderne applicaties gebruiken async/await-syntax bovenop Promise.
Future werkt op basis van event loop — de gebeurtenislus die asynchrone bewerkingen verwerkt zonder de hoofdthread te blokkeren. Wanneer een asynchrone functie wordt aangeroepen (bijv. http.get), retourneert deze onmiddellijk een Future. De werkelijke aanvraag wordt op de achtergrond uitgevoerd, terwijl de event loop andere gebeurtenissen blijft verwerken. Na voltooiing van de bewerking gaat Future naar de resolved-toestand en wordt then aangeroepen.
Event loop is het belangrijkste mechanisme waarop Dart en JavaScript zijn gebouwd. De event loop onderhoudt twee wachtrijen: microtask queue (korte taken die vóór de volgende gebeurtenis worden uitgevoerd) en event queue (IO-gebeurtenissen, timers). Future.then plaatst de callback in de microtask queue, Future.microtask — prioritaire uitvoering vóór het volgende frame.
Then()-ketens maken sequentiële verwerking van asynchrone bewerkingsresultaten mogelijk zonder callback hell. Elke then() ontvangt het resultaat van de vorige stap en retourneert een nieuwe Future. catchError() aan het einde van de keten verwerkt elke fout die in welke stap dan ook is opgetreden. Dit maakt asynchrone code lineair en leesbaar.
In Java breidt CompletableFuture het concept Future/Promise uit. De methode supplyAsync() start een asynchrone taak in ForkJoinPool.commonPool(). thenApply() transformeert het resultaat, thenCompose() — ontvouwt een geneste CompletableFuture. exceptionally() verwerkt de fout door een standaardwaarde te retourneren. allOf() en anyOf() werken als Promise.all en Promise.race in JavaScript. CompletableFuture ondersteunt handmatige voltooiing via complete() en completeExceptionally() — dit is de analoog van Promise resolve/reject.
Promise is een contract met een van drie toestanden: pending (wachtend), fulfilled (succesvol voltooid) of rejected (voltooid met fout). Na overgang naar de fulfilled- of rejected-toestand verandert Promise nooit meer — dit garandeert de onveranderlijkheid van het resultaat voor alle consumenten. De methode .then() wordt asynchroon aangeroepen na overgang naar een voltooide toestand.
Promise.all wacht op de voltooiing van alle doorgegeven promises en retourneert een array van resultaten in dezelfde volgorde. Als een promise met een fout is voltooid — gaat de gehele Promise.all naar rejected. Promise.race retourneert het resultaat van de eerst voltooide promise (succes of fout). Promise.allSettled wacht op alle promises ongeacht fouten — retourneert de status van elke.
Chaining — het belangrijkste voordeel van Promise ten opzichte van callback. Elke .then() retourneert een nieuwe Promise, waardoor ketens van willekeurige lengte kunnen worden gebouwd. Een fout in een schakel van de keten wordt doorgegeven tot de dichtstbijzijnde .catch(). De methode finally() voert code uit na voltooiing van de keten, ongeacht het resultaat — voor het opruimen van bronnen.
Eerste voorbeeld — het maken van een Future via een async-functie en verwerking via then/catchError:
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 1))
return "Gegevens geladen"
}
fetchData()
.then((result) => print(result))
.catchError((error) => print("Fout: $error"))
Tweede voorbeeld — het combineren van meerdere Futures via Future.wait:
Future<List<String>> loadAll() async {
final futures = [
fetchFromApi("/users"),
fetchFromApi("/posts"),
fetchFromApi("/comments")
]
final results = await Future.wait(futures)
return results
}
Derde voorbeeld — Promise in JavaScript met handmatige creatie en then-keten:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Klaar")
}, 1000)
})
promise
.then(value => console.log(value))
.catch(err => console.error(err))
Future/Promise verschilt van de callback-stijl doordat het een object-contract retourneert in plaats van een callback-functie als argument te accepteren. De callback-stijl leidt tot nesting (callback hell), terwijl Future het mogelijk maakt platte then()-ketens te bouwen. async/await-syntax maakt code met Future nog lineairder, vergelijkbaar met synchrone code.
Future vertegenwoordigt precies één asynchroon resultaat — één emissie, waarna Future eindigt. In tegenstelling tot Observable (Rx, ReactiveX) of Flow (Kotlin Coroutines) ondersteunt Future geen meerdere waarden in de tijd. Als u een stroom van gebeurtenissen nodig hebt — gebruik dan Stream in Dart, Observable in Rx of Flow in Kotlin.
CompletableFuture in Java — de analoog van Promise met uitgebreid API: supplyAsync, thenApply, thenCompose, exceptionally. CompletableFuture maakt het mogelijk meerdere asynchrone bewerkingen te combineren via allOf, anyOf, en ook een eigen Executor in te stellen voor uitvoering. Scala Future gebruikt ExecutionContext voor het beheren van de threadpool en ondersteunt compositie via for-comprehension.
In Dart verschilt het Future-patroon van JavaScript Promise doordat Dart strikte typering heeft: Future<String> garandeert het type van de geretourneerde waarde. async-functies in Dart moeten Future retourneren en de compiler controleert of alle paden het juiste type retourneren. Future.wait is het equivalent van Promise.all — ontvangt Iterable<Future<T>> en retourneert Future<List<T>>. Future.delayed en Future.error zijn handige fabrieken voor het testen van asynchrone scenario's.
Future/Promise is geïmplementeerd in Python via concurrent.futures.Future en asyncio.Future. concurrent.futures.ThreadPoolExecutor.submit() retourneert een Future waarop result() kan worden aangeroepen — een blokkerende aanroep. asyncio.Future is een await-compatibele container voor asynchroon resultaat in Asyncio. asyncio.gather() start meerdere coroutines parallel en retourneert een lijst met resultaten, vergelijkbaar met Promise.all in JavaScript. Python gebruikt ook callback-gebaseerd asyncio.ensure_future en add_done_callback-ketens voor compositie van asynchrone bewerkingen, maar in moderne code heeft async/await-syntax met asyncio.Task de voorkeur.
In mobiele ontwikkeling wordt Future actief gebruikt in Flutter-applicaties. Elk netwerkverzoek uit de http- of dio-pakket retourneert een Future. FutureBuilder — een widget die een Future en een status-snapshot ontvangt: connectionDone, hasData, hasError. Bij ontvangst van gegevens bevat snapshot.data het resultaat van de Future. StreamBuilder — analoog voor meerdere waarden. FutureBuilder elimineert handmatig beheer van de laadstatus via setState.
Scala Future gebruikt impliciet ExecutionContext — de threadpool waarop de asynchrone taak wordt uitgevoerd. Compositie via map, flatMap, filter werkt doordat Future een monade is. for-comprehension maakt het mogelijk meerdere Futures sequentieel te combineren zonder nesting: for { a <- futureA; b <- futureB } yield a + b. Future.sequence werkt als Promise.all. Fallback bij fout wordt gerealiseerd via recover en recoverWith.
Future/Promise in C++ wordt vertegenwoordigd door de klassen std::future en std::promise uit de bibliotheek <future>. std::async start een asynchrone functie en retourneert std::future. std::promise maakt handmatige instelling van een waarde mogelijk via set_value() of een fout via set_exception(). In tegenstelling tot Dart en JavaScript blokkeert std::future.get() de thread tot het ontvangen van het resultaat — dit is een belangrijk verschil waarmee rekening moet worden gehouden bij het ontwerpen van multi-threaded applicaties in C++.
Volg bij het ontwerpen van API's die Future retourneren de regel van enige bron van waarheid: elke asynchrone aanvraag wordt één keer gemaakt en gecachet via Future.memoize. Als twee componenten dezelfde gegevens opvragen, krijgen ze dezelfde Future — dit voorkomt duplicatie van aanvragen. Gebruik voor timeout Future.timeout (Dart) of Promise.race met een timeout om te garanderen dat de asynchrone bewerking binnen het opgegeven interval wordt voltooid.
Retry-patroon in Future wordt geïmplementeerd via een recursieve keten: bij een fout in catch wordt dezelfde asynchrone functie met vertraging aangeroepen. Exponential backoff vergroot het interval tussen pogingen: 1 sec — 2 sec — 4 sec — tot max 30 sec. In Dart wordt dit geïncapsuleerd in een extension op Future: future.retry(maxRetries: 3, delay: Duration(seconds: 1)). In Scala combineert Future.zip twee onafhankelijke resultaten in een tuple — alternatief voor Promise.all voor twee Futures. Annulering (Cancellation) wordt niet ondersteund in standaard Futures, maar wordt geïmplementeerd via CancellationToken of AbortController in JavaScript.
Veelgestelde vragen
Future is een read-only container voor het lezen van een asynchroon resultaat via then of await. Promise is een write-only contract dat een waarde ontvangt via resolve() en deze aan Future koppelt. In Dart en JavaScript zijn deze concepten verenigd: Future/Promise is één klasse. In Java en Scala zijn ze gescheiden.
Future vertegenwoordigt een enkel asynchroon resultaat — het emitteert precies één waarde en eindigt. Observable (Rx) emitteert meerdere waarden in de tijd — dit is een asynchrone stroom. Als u één HTTP-antwoord nodig hebt — gebruik dan Future. Als u een stroom van databasewijzigingen nodig hebt — gebruik dan Observable of Stream.
async/await is syntactische suiker over Future/Promise. Het sleutelwoord async markeert een functie als asynchroon — deze retourneert een Future. await onderbreekt de uitvoering tot de voltooiing van de Future, zonder de thread te blokkeren. In Dart, JavaScript, Python en C# heeft async/await then-ketens in de meeste scenario's vervangen.
Gebruik in Dart .catchError() aan het einde van de keten — dit vangt uitzonderingen in elke fase op. In JavaScript — .catch(). In Dart is ook try/await/catch binnen async-functies beschikbaar. Gebruik voor herstel na een fout .catchError() met het retourneren van een standaardwaarde of een nieuwe Future.
Promise.all ontvangt een array van promises en retourneert één Promise die wordt opgelost met een array van resultaten. Alle promises worden parallel gestart — dit versnelt de uitvoering van onafhankelijke bewerkingen (bijvoorbeeld het laden van meerdere bestanden). Als een promise wordt afgewezen — wordt de gehele Promise.all met dezelfde fout afgewezen.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook