A Future/Promise egy aszinkron programozási minta, amely egy tárolót biztosít egy még be nem fejezett művelet eredményéhez. A Dart Documentation, 2025 szerint a Future a halasztott számítások read-only eredménye, a Promise egy write-only kontraktus, amely ezt az eredményt tölti ki. A Future Dart, Java, Scala és C++ nyelvekben használatos then/catch láncokhoz.
Főbb pontok
Future/Promise egy összekapcsolt objektumpár, amely az aszinkron eredményt két szerepre osztja. A Promise megírhatja az eredményt (resolve) vagy a hibát (reject). A Future csak olvashatja — callback (then, catchError) vagy await segítségével. Ez a szétválasztás garantálja, hogy a fogyasztó nem módosíthatja az eredményt, csak használhatja.
A Dart nyelv a Future-t használja fő aszinkron mechanizmusként. A Future<T> egy kontraktus egy T típusú érték fogadására a jövőben. A Future három állapot egyikében lehet: unresolved (a művelet végrehajtás alatt), resolved with value (sikeresen befejeződött) vagy resolved with error (hibával befejeződött). A resolved állapotba lépés után a Future nem változik.
Promise JavaScriptben a Dart Future megfelelője, de gazdagabb API-val. A Promise egy executort fogad — egy függvényt resolve és reject paraméterekkel. A Promise.all, Promise.race, Promise.allSettled statikus metódusok lehetővé teszik több promise kombinálását. A modern alkalmazások async/await szintaxist használnak a Promise rétegen.
Future az event loop — eseményciklus alapján működik, amely a fő szál blokkolása nélkül dolgozza fel az aszinkron műveleteket. Amikor egy aszinkron függvény meghívódik (pl. http.get), azonnal visszaad egy Future-t. A tényleges kérés a háttérben fut, míg az event loop más eseményeket dolgoz fel. A művelet befejezése után a Future resolved állapotba lép, és a then meghívódik.
Event loop a kulcsmechanizmus, amelyre Dart és JavaScript épül. Az event loop két sort tart fenn: microtask queue (rövid feladatok, amelyek a következő esemény előtt futnak) és event queue (IO események, időzítők). A Future.then a callbacket a microtask queue-ba helyezi, a Future.microtask — prioritásos végrehajtás a következő képkocka előtt.
A then() láncok lehetővé teszik az aszinkron műveletek eredményeinek szekvenciális feldolgozását callback hell nélkül. Minden then() megkapja az előző lépés eredményét és visszaad egy új Future-t. A lánc végén lévő catchError() feldolgozza bármely lépésben felmerülő hibát. Ez lineárissá és olvashatóvá teszi az aszinkron kódot.
Java-ban a CompletableFuture kiterjeszti a Future/Promise koncepciót. A supplyAsync() metódus aszinkron feladatot indít a ForkJoinPool.commonPool()-ban. A thenApply() transzformálja az eredményt, a thenCompose() — kibontja a beágyazott CompletableFuture-t. Az exceptionally() a hibát dolgozza fel alapérték visszaadásával. Az allOf() és anyOf() úgy működnek, mint a Promise.all és Promise.race JavaScriptben. A CompletableFuture támogatja a kézi befejezést complete() és completeExceptionally() segítségével — ez a Promise resolve/reject megfelelője.
Promise egy kontraktus három állapot egyikével: pending (várakozás), fulfilled (sikeresen befejeződött) vagy rejected (hibával befejeződött). A fulfilled vagy rejected állapotba lépés után a Promise soha nem változik — ez garantálja az eredmény megváltoztathatatlanságát minden fogyasztó számára. A .then() metódus aszinkron módon hívódik meg bármely befejezett állapotba lépés után.
Promise.all megvárja az összes átadott promise befejezését, és visszaadja az eredmények tömbjét ugyanabban a sorrendben. Ha egy promise hibával fejeződött be — az egész Promise.all rejected állapotba kerül. A Promise.race az első befejezett promise eredményét adja vissza (siker vagy hiba). A Promise.allSettled megvárja az összes promise-t a hibáktól függetlenül — visszaadja mindegyik állapotát.
Chaining — a Promise legfőbb előnye a callback-kel szemben. Minden .then() új Promise-t ad vissza, lehetővé téve tetszőleges hosszúságú láncok építését. A lánc bármely szeme hibája a legközelebbi .catch()-ig terjed. A finally() metódus a lánc befejezése után fut le az eredménytől függetlenül — erőforrások felszabadítására.
Első példa — Future létrehozása async-függvényen keresztül és feldolgozás then/catchError segítségével:
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 1))
return "Adatok betöltve"
}
fetchData()
.then((result) => print(result))
.catchError((error) => print("Hiba: $error"))
Második példa — több Future kombinálása Future.wait segítségével:
Future<List<String>> loadAll() async {
final futures = [
fetchFromApi("/users"),
fetchFromApi("/posts"),
fetchFromApi("/comments")
]
final results = await Future.wait(futures)
return results
}
Harmadik példa — Promise JavaScriptben kézi létrehozással és then lánccal:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Kész")
}, 1000)
})
promise
.then(value => console.log(value))
.catch(err => console.error(err))
Future/Promise abban különbözik a callback stílustól, hogy objektum-kontraktust ad vissza ahelyett, hogy callback függvényt fogadna argumentumként. A callback stílus beágyazáshoz (callback hell) vezet, míg a Future lapos then() láncok építését teszi lehetővé. Az async/await szintaxis a Future-rel még lineárisabbá teszi a kódot, hasonlóvá a szinkron kódhoz.
Future pontosan egy aszinkron eredményt képvisel — egy kibocsátást, ami után a Future befejeződik. Ellentétben az Observable (Rx, ReactiveX) vagy Flow (Kotlin Coroutines) típusokkal, a Future nem támogat több értéket az idő múlásával. Ha eseményfolyamra van szüksége — használjon Stream-et Dartban, Observable-t Rx-ben vagy Flow-t Kotlinban.
CompletableFuture Java-ban — a Promise megfelelője kiterjesztett API-val: supplyAsync, thenApply, thenCompose, exceptionally. A CompletableFuture lehetővé teszi több aszinkron művelet kombinálását allOf, anyOf segítségével, valamint saját Executor beállítását a végrehajtáshoz. A Scala Future ExecutionContext-et használ a szálpool kezelésére és támogatja a kompozíciót for-comprehension segítségével.
Dartban a Future minta abban különbözik a JavaScript Promise-tól, hogy a Dart szigorú típusos: Future<String> garantálja a visszaadott érték típusát. Az async függvények Dartban kötelesek Future-t visszaadni, és a fordító ellenőrzi, hogy minden útvonal a megfelelő típust adja-e vissza. A Future.wait a Promise.all megfelelője — Iterable<Future<T>> fogad és Future<List<T>> ad vissza. A Future.delayed és Future.error kényelmes gyárak aszinkron forgatókönyvek teszteléséhez.
A Future/Promise Python-ban a concurrent.futures.Future és asyncio.Future segítségével van implementálva. A concurrent.futures.ThreadPoolExecutor.submit() egy Future-t ad vissza, amelyen meghívható a result() — egy blokkoló hívás. Az asyncio.Future egy await-kompatibilis tároló aszinkron eredményhez az Asyncioban. Az asyncio.gather() párhuzamosan indít több korutint és visszaadja az eredmények listáját, hasonlóan a Promise.all-hoz JavaScriptben. A Python also használ callback-alapú asyncio.ensure_future-t és add_done_callback láncokat aszinkron műveletek kompozíciójához, de modern kódban az async/await szintaxis asyncio.Task-kal preferált.
A mobilfejlesztésben a Future aktívan használatos Flutter alkalmazásokban. Minden hálózati kérés a http vagy dio csomagból Future-t ad vissza. A FutureBuilder — egy widget, amely Future-t és állapot snapshot-ot fogad: connectionDone, hasData, hasError. Az adatok fogadásakor a snapshot.data tartalmazza a Future eredményét. A StreamBuilder — a megfelelője több értékhez. A FutureBuilder kiküszöböli a betöltési állapot kézi kezelését setState segítségével.
A Scala Future implicit módon használ ExecutionContext-et — azt a szálpoolt, amelyen az aszinkron feladat fut. A map, flatMap, filter segítségével történő kompozíció azért működik, mert a Future egy monád. A for-comprehension lehetővé teszi több Future szekvenciális kombinálását beágyazás nélkül: for { a <- futureA; b <- futureB } yield a + b. A Future.sequence úgy működik, mint a Promise.all. A hiba esetén visszaállás a recover és recoverWith segítségével valósul meg.
Future/Promise C++-ban a <future> könyvtár std::future és std::promise osztályai képviselik. A std::async elindít egy aszinkron függvényt és std::future-t ad vissza. A std::promise lehetővé teszi az érték kézi beállítását set_value() vagy a hiba beállítását set_exception() segítségével. Ellentétben Darttal és JavaScripttel, a std::future.get() blokkolja a szálat az eredmény megérkezéséig — ez egy fontos különbség, amelyet figyelembe kell venni többszálú alkalmazások tervezésekor C++-ban.
Future-t visszaadó API-k tervezésekor kövesse az egyetlen igazságforrás szabályát: minden aszinkron kérés egyszer jön létre, és Future.memoize segítségével cache-elődik. Ha két komponens ugyanazokat az adatokat kéri, ugyanazt a Future-t kapják — ez megakadályozza a kérések duplikálódását. Időtúllépéshez használjon Future.timeout (Dart) vagy Promise.race időtúllépéssel, hogy garantálja az aszinkron művelet befejeződését a megadott intervallumon belül.
Retry minta Future-ben rekurzív láncon keresztül valósul meg: hiba esetén a catch-ben ugyanaz az aszinkron függvény hívódik meg késleltetéssel. Az Exponential backoff növeli a próbálkozások közötti intervallumot: 1 mp — 2 mp — 4 mp — max 30 mp. Dartban ez egy Future kiterjesztésbe van kapszulázva: future.retry(maxRetries: 3, delay: Duration(seconds: 1)). Scala-ban a Future.zip két független eredményt egyesít egy tuple-be — alternatíva a Promise.all-hoz két Future esetén. A megszakítás (Cancellation) nem támogatott a standard Future-ökben, de CancellationToken vagy AbortController segítségével valósítható meg JavaScriptben.
Gyakran Ismételt Kérdések
Future egy read-only tároló aszinkron eredmény olvasásához then vagy await segítségével. A Promise egy write-only kontraktus, amely a resolve() segítségével fogad egy értéket, és összekapcsolja a Future-rel. Dartban és JavaScriptben ezek a fogalmak egyesültek: a Future/Promise egy osztály. Java-ban és Scala-ban külön vannak.
Future egyetlen aszinkron eredményt képvisel — pontosan egy értéket bocsát ki és befejeződik. Az Observable (Rx) több értéket bocsát ki az idő múlásával — ez egy aszinkron adatfolyam. Ha egy HTTP-válaszra van szüksége — használjon Future-t. Ha adatbázis-változások folyamára van szüksége — használjon Observable-t vagy Stream-et.
async/await szintaktikai cukor a Future/Promise felett. Az async kulcsszó aszinkronként jelöl meg egy függvényt — az Future-t ad vissza. Az await felfüggeszti a végrehajtást a Future befejeződéséig, a szál blokkolása nélkül. Dart, JavaScript, Python és C# nyelvekben az async/await a legtöbb esetben felváltotta a then láncokat.
Dartban használja a .catchError() metódust a lánc végén — ez bármely szakaszban elkapja a kivételeket. JavaScriptben — .catch(). Dartban try/await/catch is elérhető async függvényeken belül. Hiba utáni helyreállításhoz használja a .catchError()-t egy alapérték vagy új Future visszaadásával.
Promise.all fogad egy promise tömböt és visszaad egy Promise-t, amely az eredmények tömbjével oldódik fel. Az összes promise párhuzamosan indul — ez felgyorsítja a független műveletek végrehajtását (pl. több fájl betöltése). Ha bármely promise elutasításra kerül — az egész Promise.all ugyanazzal a hibával utasíttatik el.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is