Future/Promise — mi ez, aszinkron számítások és programozás

Szerző: IT Sectr Megjelenés: 2026-03-17 Olvasási idő: 9 perc

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 — read-only tároló a jövőben elérhető aszinkron eredményhez
  • Promise — write-only kitöltő, amely fogadja az eredményt és továbbítja a Future-nek
  • Then láncok — aszinkron műveletek szekvenciális feldolgozása beágyazott callbackek nélkül
  • Future Dartban — az async/await és a dio, http, shelf könyvtárak alapja
  • Future/Promise — alternatíva a callback mintára és az async/await szintaxis alapja

Mi az a Future/Promise?

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.

Future Dartban

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

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.

Hogyan működik a Future

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.

CompletableFuture Java-ban

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 és az aszinkron kontraktus

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.

Future kódpéldák (Dart)

Első példa — Future létrehozása async-függvényen keresztül és feldolgozás then/catchError segítségével:

dart
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:

dart
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:

js
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("Kész")
    }, 1000)
})

promise
    .then(value => console.log(value))
    .catch(err => console.error(err))

Future vs más aszinkron minták

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.

Munkaminták Future-rel

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

Mi a különbség a Future és a Promise között?

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.

Miben különbözik a Future az Observable-től?

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.

Mi az async/await és hogyan kapcsolódik a Future-höz?

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.

Hogyan kezeljük a hibákat egy Future láncban?

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.

Mi az a Promise.all és mikor használjuk?

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

  • Future/Promise — aszinkron programozási minta kontraktussal egy értékre
  • Future — read-only tároló a művelet eredményének olvasásához
  • Promise — write-only kontraktus, amely kitölti a Future-t resolve/reject segítségével
  • Then láncok — lapos aszinkron lépések feldolgozása callback hell nélkül
  • async/await — szintaktikai cukor a Future felett, lineárissá teszi a kódot
  • Promise.all — több aszinkron művelet párhuzamos indítása
  • Több értékhez az idő múlásával használjon Stream-et vagy Observable-t, ne Future-t

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.

Projekt megbeszélése

Olvassa el is