async: шта је то, Deferred и паралелне корутине како раде

Аутор: IT Sectr Објављено: 2026-06-22 Време читања: 8 мин

async — Coroutine Builder у Kotlin-у који покреће корутину и враћа објекат Deferred<T> за добијање резултата асинхроне операције. async омогућава паралелно извршавање више задатака и агрегирање њихових резултата преко await(). Према JetBrains водичу, 2024, async је пожељан начин организације паралелних израчунавања у корутинама.

Главно

  • async — градитељ корутина који враћа Deferred<T> са резултатом асинхроне операције
  • Deferred — асинхроно обећање, наследник Job, са методом await() за добијање резултата
  • async омогућава паралелно извршавање независних задатака, смањујући укупно вријеме
  • await() — suspend-функција која зауставља корутину до добијања резултата без блокирања
  • Структурирана конкурентност са async гарантује отказивање свих паралелних задатака при грешци

Шта је async у Kotlin Coroutines?

async — функција проширења CoroutineScope која ствара корутину са враћањем резултата. За разлику од launch, async враћа Deferred<T> — објекат који представља будућу вриједност. Корутина покренута преко async извршава се конкурентно са другим корутинама, што омогућава паралелизацију израчунавања.

async се користи када је резултат асинхроне операције потребан за даљу обраду: учитавање података из више извора, пакетна обрада колекција, паралелни захтјеви различитим API-јима. Deferred се ствара одмах, а резултат постаје доступан након завршетка корутине.

kotlin
import kotlinx.coroutines.*

suspend fun String.delayedValue(): String {
    delay(1000L)
    return this
}

fun main() = runBlocking {
    val deferred: Deferred<String> = async { "Hello".delayedValue() }
    println(deferred.await())
}

Синтакса async и Deferred

Потпис async је сличан launch: исти параметри CoroutineContext, CoroutineStart и suspend-блок. Разлика је у типу који се враћа — Deferred<T> умјесто Job, гдје је T тип резултата који враћа посљедњи израз блока.

kotlin
public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T>

Deferred<T> — интерфејс који насљеђује Job и додаје методе await(), getCompleted(), getCompletionExceptionOrNull(). await() је suspend-функција и може се позвати само унутар корутине или друге suspend-функције. getCompleted() — метод који не блокира, баца изузетак ако корутина још није завршена.

Паралелни задаци са async

Главна предност async-а је могућност покретања задатака паралелно. Умјесто секвенцијалног чекања на сваку операцију (укупно вријеме = збир времена), async покреће корутине истовремено, смањујући укупно вријеме на вријеме најдуже операције.

Паралелно учитавање података

Типичан сценарио — учитавање профила корисника, његових поставки и историје наруџбина са три паралелна async захтјева. Након завршетка све три, резултати се обједињују у јединствени модел података.

kotlin
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
    val profile = async { api.getProfile(userId) }
    val settings = async { api.getSettings(userId) }
    val orders = async { api.getRecentOrders(userId) }

    Dashboard(
        profile = profile.await(),
        settings = settings.await(),
        orders = orders.await()
    )
}

Функција coroutineScope покреће подређене корутине и чека њихов завршетак прије враћања резултата. Цијели блок се извршава паралелно, а не секвенцијално.

Обрада резултата Deferred

Deferred подржава неколико метода за рад са резултатом. Поред await(), доступне су методе за провјеру статуса, добијање готове вриједности и агрегацију више Deferred преко помоћних функција Kotlin Coroutines.

МетодОписSuspend?
await()Зауставља корутину до добијања резултатаДа
getCompleted()Враћа резултат ако је корутина завршена (иначе Exception)Не
getCompletionExceptionOrNull()Враћа изузетак при грешци или nullНе
isCompletedПровјерава да ли је корутина завршенаНе

За агрегацију листе Deferred користи се awaitAll() — функција која зауставља извршавање док се не заврше сви Deferred у колекцији. Ако се барем један завршио са грешком, awaitAll() баца изузетак.

kotlin
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
    return coroutineScope {
        val deferreds = requests.map { async { it() } }
        deferreds.awaitAll()
    }
}

Разлике између async и launch

Избор између async и launch зависи од тога да ли је потребан резултат извршавања корутине. launch враћа Job и погодан је за fire-and-forget операције, async враћа Deferred и користи се за задатке који враћају податке. По синтакси и параметрима градитељи су идентични.

  • launch → Job (нема резултата), async → Deferred<T> (има резултат T)
  • launch — fire-and-forget задаци (логовање, кеширање, слање аналитике)
  • async — паралелна израчунавања (учитавање са више API-ја, пакетна обрада)
  • Оба подржавају структурирану конкурентност и параметре CoroutineStart
  • await() је доступан само за Deferred, launch не обезбјеђује резултат

Важно правило: never use async for fire-and-forget. Ако резултат корутине није потребан, користите launch. async ствара додатни трошак за стварање Deferred, који у таквом сценарију није оправдан.

Примјери async у мобилном развоју

У Android-у async се користи за паралелне операције унутар ViewModel и UseCases. Типични сценарији: истовремено учитавање профила и вијести, добијање времена са више метео сервиса, пакетна синхронизација података са сервером.

kotlin
class HomeViewModel : ViewModel() {
    fun loadHomeScreen() {
        viewModelScope.launch {
            val userData = async(Dispatchers.IO) { repository.getUserData() }
            val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
            val notifications = async(Dispatchers.IO) { repository.getNotifications() }

            val state = HomeState(
                user = userData.await(),
                news = newsFeed.await(),
                unread = notifications.await()
            )
            _uiState.update { state }
        }
    }
}

Препоручује се умотавање групе async у coroutineScope или supervisorScope ради изолације грешака. supervisorScope омогућава наставак извршавања осталих async корутина чак и при грешци у једној од њих — корисно за некритичне операције.

Често постављана питања

Може ли се користити async без await?

Може, али бесмислено. async без await() покреће корутину, али њен резултат се губи. Ако резултат није потребан, користите launch — он не ствара Deferred и ефикаснији је по меморији и перформансама.

Како async обрађује изузетке?

Изузетак унутар async се чува у Deferred. Позив await() преноси овај изузетак. За провјеру без преношења користите getCompletionExceptionOrNull(). При коришћењу coroutineScope грешка отказује све подређене корутине.

Шта је awaitAll у Kotlin Coroutines?

awaitAll() — функција проширења за Iterable<Deferred<T>> која зауставља корутину док се не заврше сви Deferred. Враћа листу резултата. Ако се барем један Deferred заврши са грешком, преноси изузетак и отказује остале.

Разликује ли се async од GlobalScope.async?

Да. async — функција проширења CoroutineScope, везана за scope. GlobalScope.async ствара корутину без повезивања са животним циклусом — може се извршавати бесконачно. У Android-у GlobalScope се не препоручује због ризика од цурења меморије.

Колико async корутина се може покренути за паралелне захтјеве?

Број диктира диспечер: Dispatchers.IO подржава до 64 истовремене нити, Dispatchers.Default — по броју CPU језгара. За масовне операције користите ограничени паралелизам преко Semaphore или mapNotNull са awaitAll.

Закључци

  • async — градитељ корутина који враћа Deferred<T> за асинхроно добијање резултата
  • Deferred насљеђује Job и додаје методе await(), getCompleted(), getCompletionExceptionOrNull()
  • Паралелно извршавање са async смањује укупно вријеме на трајање најдуже операције
  • awaitAll() — помоћни алат за чекање свих Deferred у колекцији
  • coroutineScope — препоручени омотач за групу async са гаранцијом отказивања
  • Не користите async за fire-and-forget — примијените launch
  • У Android-у async се користи за паралелно учитавање у ViewModel са viewModelScope

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође