async: co to je, Deferred a paralelní koroutiny jak fungují

Autor: IT Sectr Publikováno: 2026-06-22 Doba čtení: 8 min

async — Coroutine Builder v Kotlinu, který spouští koroutinu a vrací objekt Deferred<T> pro získání výsledku asynchronní operace. async umožňuje paralelní provádění více úkolů a agregaci jejich výsledků pomocí await(). Podle průvodce JetBrains, 2024 je async preferovaným způsobem organizace paralelních výpočtů v koroutinách.

Hlavní body

  • async — stavitel koroutin, který vrací Deferred<T> s výsledkem asynchronní operace
  • Deferred — asynchronní příslib, dědící Job, s metodou await() pro získání výsledku
  • async umožňuje paralelní provádění nezávislých úkolů, čímž zkracuje celkový čas
  • await() — suspend-funkce, která pozastavuje koroutinu do získání výsledku bez blokování
  • Strukturovaná souběžnost s async zaručuje zrušení všech paralelních úkolů při chybě

Co je async v Kotlin Coroutines?

async — je rozšiřující funkce CoroutineScope, která vytváří koroutinu s vracením výsledku. Na rozdíl od launch, async vrací Deferred<T> — objekt představující budoucí hodnotu. Koroutina spuštěná přes async se provádí souběžně s ostatními koroutinami, což umožňuje paralelizaci výpočtů.

async se používá, když je výsledek asynchronní operace potřebný pro další zpracování: načítání dat z více zdrojů, dávkové zpracování kolekcí, paralelní požadavky na různá API. Deferred je vytvořen okamžitě a výsledek je k dispozici po dokončení koroutiny.

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())
}

Syntaxe async a Deferred

Signatura async je podobná launch: stejné parametry CoroutineContext, CoroutineStart a suspend-blok. Rozdíl je v návratovém typu — Deferred<T> místo Job, kde T je typ výsledku vráceného posledním výrazem bloku.

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

Deferred<T> — rozhraní, které dědí Job a přidává metody await(), getCompleted(), getCompletionExceptionOrNull(). await() je suspend-funkce a může být volána pouze uvnitř koroutiny nebo jiné suspend-funkce. getCompleted() — neblokující metoda, která vyvolá výjimku, pokud koroutina ještě nebyla dokončena.

Paralelní úkoly s async

Hlavní výhodou async je možnost spouštět úkoly paralelně. Místo sekvenčního čekání na každou operaci (celkový čas = součet časů) async spouští koroutiny současně, čímž zkracuje celkový čas na čas nejdelší operace.

Paralelní načítání dat

Typický scénář — načítání profilu uživatele, jeho nastavení a historie objednávek třemi paralelními async požadavky. Po dokončení všech tří jsou výsledky sloučeny do jediného datového modelu.

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()
    )
}

Funkce coroutineScope spouští podřízené koroutiny a čeká na jejich dokončení před vrácením výsledku. Celý blok se provádí paralelně, ne sekvenčně.

Zpracování výsledků Deferred

Deferred podporuje několik metod pro práci s výsledkem. Kromě await() jsou k dispozici metody pro kontrolu stavu, získání hotové hodnoty a agregaci více Deferred pomocí pomocných funkcí Kotlin Coroutines.

MetodaPopisSuspend?
await()Pozastaví koroutinu do získání výsledkuAno
getCompleted()Vrátí výsledek, pokud je koroutina dokončena (jinak Exception)Ne
getCompletionExceptionOrNull()Vrátí výjimku při chybě nebo nullNe
isCompletedZkontroluje, zda je koroutina dokončenaNe

Pro agregaci seznamu Deferred se používá awaitAll() — funkce, která pozastaví provádění, dokud nejsou dokončeny všechny Deferred v kolekci. Pokud alespoň jeden skončil chybou, awaitAll() vyvolá výjimku.

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

Rozdíly mezi async a launch

Výběr mezi async a launch závisí na tom, zda je potřeba výsledek provádění koroutiny. launch vrací Job a je vhodný pro operace fire-and-forget, async vrací Deferred a používá se pro úkoly vracející data. Z hlediska syntaxe a parametrů jsou stavitelé identičtí.

  • launch → Job (bez výsledku), async → Deferred<T> (má výsledek T)
  • launch — fire-and-forget úkoly (logování, cachování, odesílání analytiky)
  • async — paralelní výpočty (načítání z více API, dávkové zpracování)
  • Oba podporují strukturovanou souběžnost a parametry CoroutineStart
  • await() je k dispozici pouze pro Deferred, launch neposkytuje výsledek

Důležité pravidlo: nikdy nepoužívejte async pro fire-and-forget. Pokud výsledek koroutiny není potřeba, použijte launch. async vytváří režii na vytvoření Deferred, která není v takovém scénáři ospravedlnitelná.

Příklady async v mobilním vývoji

V Androidu se async používá pro paralelní operace uvnitř ViewModel a UseCases. Typické scénáře: současné načítání profilu a zpravodajského kanálu, získávání počasí z více meteorologických služeb, dávková synchronizace dat se serverem.

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 }
        }
    }
}

Doporučuje se zabalit skupinu async do coroutineScope nebo supervisorScope pro izolaci chyb. supervisorScope umožňuje pokračovat v provádění ostatních async koroutin i při chybě v jedné z nich — užitečné pro nekritické operace.

Často kladené otázky

Lze async použít bez await?

Lze, ale je to zbytečné. async bez await() spouští koroutinu, ale její výsledek se ztrácí. Pokud výsledek není potřeba, použijte launch — nevytváří Deferred a je efektivnější z hlediska paměti a výkonu.

Jak async zpracovává výjimky?

Výjimka uvnitř async je uložena v Deferred. Volání await() tuto výjimku propaguje. Pro kontrolu bez propagace použijte getCompletionExceptionOrNull(). Při použití coroutineScope chyba zruší všechny podřízené koroutiny.

Co je awaitAll v Kotlin Coroutines?

awaitAll() — rozšiřující funkce pro Iterable<Deferred<T>>, která pozastaví koroutinu, dokud nejsou dokončeny všechny Deferred. Vrací seznam výsledků. Pokud alespoň jeden Deferred skončí chybou, propaguje výjimku a zruší ostatní.

Liší se async od GlobalScope.async?

Ano. async je rozšiřující funkce CoroutineScope, vázaná na scope. GlobalScope.async vytváří koroutinu bez vazby na životní cyklus — může běžet donekonečna. V Androidu se GlobalScope nedoporučuje kvůli riziku úniků paměti.

Kolik async koroutin lze spustit pro paralelní požadavky?

Počet je dán dispečerem: Dispatchers.IO podporuje až 64 současných vláken, Dispatchers.Default — podle počtu jader CPU. Pro hromadné operace používejte omezený paralelismus přes Semaphore nebo mapNotNull s awaitAll.

Shrnutí

  • async — stavitel koroutin vracející Deferred<T> pro asynchronní získání výsledku
  • Deferred dědí Job a přidává metody await(), getCompleted(), getCompletionExceptionOrNull()
  • Paralelní provádění s async zkracuje celkový čas na dobu trvání nejdelší operace
  • awaitAll() — nástroj pro čekání na všechny Deferred v kolekci
  • coroutineScope — doporučený obal pro skupinu async se zárukou zrušení
  • Nepoužívejte async pro fire-and-forget — aplikujte launch
  • V Androidu se async používá pro paralelní načítání ve ViewModel s viewModelScope

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také