Future/Promise је образац асинхроног програмирања који представља контејнер за резултат још незавршене операције. Према Dart Documentation, 2025, Future је read-only резултат одложених израчунавања, Promise је write-only уговор који попуњава овај резултат. Future се користи у Dart, Java, Scala и C++ за ланце then/catch.
Главно
Future/Promise је пар повезаних објеката који деле асинхрони резултат на две улоге. Promise може да запише резултат (resolve) или грешку (reject). Future може само да га чита — преко callback-а (then, catchError) или преко await-а. Таква подела гарантује да потрошач не може да промени резултат, већ само да га користи.
Језик Dart користи Future као главни механизам асинхроности. Future<T> је уговор за добијање вредности типа T у будућности. Future може бити у једном од три стања: unresolved (операција се извршава), resolved with value (успешно завршена) или resolved with error (завршена са грешком). Након преласка у resolved стање, Future се не мења.
Promise у JavaScript-у је аналог Dart-овог Future-а, али са богатијим API-јем. Promise прима егзекутор — функцију са параметрима resolve и reject. Статички методи Promise.all, Promise.race, Promise.allSettled омогућавају комбиновање више промиса. Савремене апликације користе async/await синтаксу изнад Promise-а.
Future ради на основу event loop-а — петље догађаја која обрађује асинхроне операције без блокирања главне нити. Када се позове асинхрона функција (нпр. http.get), она одмах враћа Future. Стварни захтев се извршава у позадини, а event loop наставља да обрађује друге догађаје. Након завршетка операције, Future прелази у resolved стање и позива се then.
Event loop је кључни механизам на коме су изграђени Dart и JavaScript. Event loop одржава два реда: microtask queue (кратки задаци који се извршавају пре следећег догађаја) и event queue (IO догађаји, тајмери). Future.then смешта callback у microtask queue, Future.microtask — приоритетно извршавање пре следећег кадра.
Ланци then() омогућавају секвенцијалну обраду резултата асинхроних операција без callback hell-а. Сваки then() добија резултат претходног корака и враћа нови Future. catchError() на крају ланца обрађује било коју грешку која се појавила у било ком кораку. Ово чини асинхрони код линеарним и читљивим.
У Java-и CompletableFuture проширује концепт Future/Promise. Метод supplyAsync() покреће асинхрони задатак у ForkJoinPool.commonPool(). thenApply() трансформише резултат, thenCompose() — развија угнежђени CompletableFuture. exceptionally() обрађује грешку са враћањем подразумеване вредности. allOf() и anyOf() раде као Promise.all и Promise.race у JavaScript-у. CompletableFuture подржава ручно завршавање кроз complete() и completeExceptionally() — ово је аналог Promise resolve/reject.
Promise је уговор са једним од три стања: pending (чекање), fulfilled (успешно завршен) или rejected (завршен са грешком). Након преласка у fulfilled или rejected стање, Promise се никада не мења — ово гарантује имутабилност резултата за све потрошаче. Метод .then() се позива асинхроно након преласка у било које завршно стање.
Promise.all чека завршетак свих прослеђених промиса и враћа низ резултата у истом редоследу. Ако се један промис завршио грешком — цео Promise.all прелази у rejected. Promise.race враћа резултат првог завршеног промиса (успех или грешка). Promise.allSettled чека све промисe без обзира на грешке — враћа статус сваког.
Chaining — кључна предност Promise-а у односу на callback. Сваки .then() враћа нови Promise, омогућавајући изградњу ланаца произвољне дужине. Грешка у било којој карици ланца се преноси до најближег .catch(). Метод finally() извршава код након завршетка ланца без обзира на резултат — за чишћење ресурса.
Први пример — креирање Future-а кроз async-функцију и обрада кроз then/catchError:
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 1))
return "Подаци су учитани"
}
fetchData()
.then((result) => print(result))
.catchError((error) => print("Грешка: $error"))
Други пример — комбиновање више Future-а кроз Future.wait:
Future<List<String>> loadAll() async {
final futures = [
fetchFromApi("/users"),
fetchFromApi("/posts"),
fetchFromApi("/comments")
]
final results = await Future.wait(futures)
return results
}
Трећи пример — Promise у JavaScript-у са ручним креирањем и ланцем then:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Готово")
}, 1000)
})
promise
.then(value => console.log(value))
.catch(err => console.error(err))
Future/Promise се разликује од callback стила по томе што враћа објекат-уговор уместо да прима функцију повратног позива као аргумент. Callback стил доводи до угнежђивања (callback hell), док Future омогућава изградњу равних ланаца then(). async/await синтакса чини код са Future-ом још линеарнијим, сличним синхроном.
Future представља тачно један асинхрони резултат — једну емисију, након чега се Future завршава. За разлику од Observable (Rx, ReactiveX) или Flow (Kotlin Coroutines), Future не подржава вишеструке вредности током времена. Ако је потребан ток догађаја — користите Stream у Dart-у, Observable у Rx-у или Flow у Kotlin-у.
CompletableFuture у Java-и — аналог Promise-а са проширеним API-јем: supplyAsync, thenApply, thenCompose, exceptionally. CompletableFuture омогућава комбиновање више асинхроних операција кроз allOf, anyOf, као и постављање сопственог Executor-а за извршење. Scala Future користи ExecutionContext за управљање pool-ом нити и подржава композицију кроз for-comprehension.
У Dart-у се образац Future разликује од JavaScript Promise-а по томе што Dart има строгу типизацију: Future<String> гарантује тип повратне вредности. async функције у Dart-у морају да враћају Future, а компајлер проверава да ли све путање враћају исправан тип. Future.wait је еквивалент Promise.all-у — прима Iterable<Future<T>> и враћа Future<List<T>>. Future.delayed и Future.error су згодне фабрике за тестирање асинхроних сценарија.
Future/Promise је имплементиран у Python-у кроз concurrent.futures.Future и asyncio.Future. concurrent.futures.ThreadPoolExecutor.submit() враћа Future на коме се може позвати result() — блокирајући позив. asyncio.Future је await-компатибилан контејнер за асинхрони резултат у Asyncio-у. asyncio.gather() паралелно покреће више корутина и враћа листу резултата, слично Promise.all-у у JavaScript-у. Python такође користи callback-based asyncio.ensure_future и ланце add_done_callback за композицију асинхроних операција, али се у савременом коду предност даје async/await синтакси са asyncio.Task.
У мобилном развоју Future се активно користи у Flutter апликацијама. Сваки мрежни захтев из пакета http или dio враћа Future. FutureBuilder — widget који прима Future и snapshot стања: connectionDone, hasData, hasError. По пријему података, snapshot.data садржи резултат Future-а. StreamBuilder — аналог за вишеструке вредности. FutureBuilder елиминише ручно управљање стањем учитавања кроз setState.
Scala Future имплицитно користи ExecutionContext — pool нити на коме се извршава асинхрони задатак. Композиција кроз map, flatMap, filter функционише захваљујући томе што је Future монада. for-comprehension омогућава секвенцијално комбиновање више Future-а без угнежђивања: for { a <- futureA; b <- futureB } yield a + b. Future.sequence ради као Promise.all. Повратак на резервну вредност при грешци се реализује кроз recover и recoverWith.
Future/Promise у C++-у је представљен класама std::future и std::promise из библиотеке <future>. std::async покреће асинхрону функцију и враћа std::future. std::promise омогућава ручно постављање вредности кроз set_value() или грешке кроз set_exception(). За разлику од Dart-а и JavaScript-а, std::future.get() блокира нит до добијања резултата — ово је важна разлика коју треба узети у обзир при пројектовању вишеструконитних апликација у C++-у.
При пројектовању API-ја који враћају Future, придржавајте се правила јединственог извора истине: сваки асинхрони захтев се креира једном и кешира кроз Future.memoize. Ако две компоненте захтевају исте податке, оне добијају исти Future — ово спречава дуплирање захтева. За timeout користите Future.timeout (Dart) или Promise.race са timeout-ом да бисте гарантовали да ће се асинхрона операција завршити у оквиру задатог интервала.
Retry образац у Future-у се реализује кроз рекурзивни ланац: при грешци у catch-у се позива иста асинхрона функција са кашњењем. Exponential backoff повећава интервал између покушаја: 1 сек — 2 сек — 4 сек — до макс 30 сек. У Dart-у се ово инкапсулира у extension на Future: future.retry(maxRetries: 3, delay: Duration(seconds: 1)). У Scala-и Future.zip спаја два независна резултата у tuple — алтернатива Promise.all-у за два Future-а. Отказивање (Cancellation) у стандардним Future-има није подржано, али се реализује кроз CancellationToken или AbortController у JavaScript-у.
Често постављана питања
Future је read-only контејнер за читање асинхроног резултата кроз then или await. Promise је write-only уговор који прихвата вредност кроз resolve() и повезује је са Future-ом. У Dart-у и JavaScript-у су ови појмови обједињени: Future/Promise је једна класа. У Java-и и Scala-и су раздвојени.
Future представља један асинхрони резултат — емитује тачно једну вредност и завршава се. Observable (Rx) емитује вишеструке вредности током времена — то је асинхрони ток. Ако вам је потребан један HTTP одговор — користите Future. Ако вам је потребан ток промена базе података — користите Observable или Stream.
async/await је синтаксни шећер изнад Future/Promise. Кључна реч async означава функцију као асинхрону — она враћа Future. await зауставља извршавање до завршетка Future-а, не блокирајући нит. У Dart-у, JavaScript-у, Python-у и C#-у, async/await је заменио ланце then у већини сценарија.
У Dart-у користите .catchError() на крају ланца — он хвата изузетке у било којој фази. У JavaScript-у — .catch(). У Dart-у је такође доступан try/await/catch унутар async функција. За опоравак након грешке користите .catchError() са враћањем подразумеване вредности или новог Future-а.
Promise.all прима низ промиса и враћа један Promise који се разрешава низом резултата. Сви промисu се покрећу паралелно — ово убрзава извршавање независних операција (нпр. учитавање више датотека). Ако је било који промис одбијен — цео Promise.all се одбија са истом грешком.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође