Async/Await: podstata, async funkce a práce s await

Autor: IT Sectr Publikováno: 2026-03-16 Doba čtení: 8 min

Async/Await — to je dvojice klíčových slov pro psaní asynchronního kódu v synchronním stylu, dostupná ve Swift od iOS 13 a v Kotlin s korutinami. Podle Apple Swift Documentation, 2026, Async/Await nahrazuje řetězce callbacků a GCD, čímž činí asynchronní kód lineárním a čitelným. Klíčové slovo async označuje funkci jako asynchronní a await pozastavuje její provádění až do získání výsledku.

Hlavní body

  • Async/Await — syntaktický cukr pro asynchronní kód bez vnořených callbacků
  • async označuje funkci jako asynchronní a pozastavitelnou
  • await pozastavuje provádění funkce do dokončení asynchronní operace
  • Task ve Swift vytváří novou asynchronní jednotku práce s kontextem
  • Structured Concurrency zaručuje, že všechny podřízené úkoly jsou dokončeny před nadřazeným

Co je Async/Await a asynchronní programování

Async/Await — to je jazyková konstrukce, která umožňuje psát asynchronní kód stejně lineárně jako synchronní. Ve Swift se objevila v iOS 13 / macOS 10.15 společně s frameworkem Swift Concurrency. V Kotlin je async/await dostupný přes knihovnu korutin (kotlinx.coroutines) od verze 1.3.

Před příchodem async/await se asynchronní kód stavěl na callback, GCD nebo RxSwift. Řetězce vnořených callbacků vedly k callback hell — hlubokému vnoření, které komplikuje čtení a ladění. Async/Await tento problém řeší tím, že asynchronní funkce se mohou „pozastavit“ v bodech await a obnovit se po získání výsledku.

Podle údajů Google (2025), použití async/await v Kotlin snižuje počet řádků asynchronního kódu o 40–60 % ve srovnání s přístupem callbacků. Ve Swift dosáhlo přijetí Swift Concurrency 68 % mezi publikovanými aplikacemi v roce 2025. iOS 16 přidala podporu Swift Concurrency v UIKit, SwiftUI a Foundation, což učinilo async/await standardním nástrojem pro všechny nové projekty Apple.

Princip fungování: pozastavitelné funkce

Klíčový rozdíl async/await od vláken — pozastavení bez blokování. Když funkce narazí na await, pozastaví se a uvolní aktuální vlákno pro jiné úkoly. Po dokončení asynchronní operace se funkce obnoví na stejném nebo jiném vlákně. Tomu se říká cooperative multitasking.

Jak Async/Await funguje: pozastavení a obnovení

Async funkce je kompilována do state machine — konečného automatu, který řídí stavy provádění. V bodě await kompilátor uloží kontext (lokální proměnné, adresu návratu) a předá řízení runtime. Když je výsledek připraven, runtime obnoví kontext a pokračuje v provádění.

Ve Swift je tato state machine implementována na úrovni kompilátoru SIL (Swift Intermediate Language). V Kotlin — pomocí mechanismu Continuation Passing Style (CPS): každá suspend funkce přijímá skrytý parametr Continuation, prostřednictvím kterého se vrací výsledek. Oba přístupy zaručují bezpečné obnovení bez úniků paměti.

  • Swift — kompilátor překládá async funkci do SIL s runAsync coroutine frame
  • Kotlin — každá suspend funkce získává Continuation a deleguje provádění dispečerovi
  • Oba jazyky — uvolňují vlákno při await, aniž by ho blokovaly na dobu čekání
  • Výjimky — jsou propagovány standardními mechanismy (throws / try-catch)

Async/Await vs Callbacks a GCD: srovnání přístupů

Callback přístup vyžaduje předání uzavření, které je voláno po dokončení operace. Při třech po sobě jdoucích požadavcích vznikají tři úrovně vnoření s ošetřením chyb na každé. Async/Await mění stejné tři požadavky na tři po sobě jdoucí řádky s jediným blokem catch.

GCD (DispatchQueue) řeší problém callback hell pomocí sériových front a DispatchGroup, ale zůstává mnohomluvný. Pro jednoduchý úkol — načíst user, poté friends, poté UI — je třeba vytvoření front, skupin a notify bloků. Async/Await provádí stejný úkol třemi řádky v jedné funkci.

AspektCallbackGCDAsync/Await
VnořeníHluboké (pyramid of doom)Střední (skupiny+notify)Lineární (flat)
Ošetření chybPer-callbackRučníJednotné (try/catch)
ZrušeníRučníOmezenéTask.cancel()
Thread safetyRučníPřes sériovou frontuPřes MainActor

Podle údajů Apple WWDC 2024, Swift Concurrency async/await — doporučený přístup pro nový kód. GCD zůstává pro integraci s C-knihovnami a specifické low-level scénáře zpracování vláken.

Swift Concurrency: Task, TaskGroup a Actor

Task — to je základní jednotka asynchronní práce ve Swift. Task se vytváří v kontextu existujícího aktoru nebo na libovolném vlákně. Uvnitř Task lze volat async funkce přes await. TaskGroup umožňuje spouštět několik podřízených úkolů paralelně a sbírat jejich výsledky — obdoba DispatchGroup na steroidech.

Actor — vláknově bezpečný reference type, který chraní svůj stav před datovými závody. Kompilátor zaručuje, že přístup k vlastnostem actor je možný pouze přes async volání nebo v rámci actor isolation. Actor nahrazuje sériovou DispatchQueue pro ochranu shared mutable state bez ručních zámků.

Structured Concurrency

Princip Structured Concurrency říká: každý asynchronní úkol má rodiče a rodič se nedokončí, dokud nejsou dokončeny všechny jeho děti. Pokud úkol A spustí Task { await B() }, pak A čeká na B. To zabraňuje úniku úkolů a zajišťuje předvídatelný lifecycle.

Async/Await v Kotlin s korutinami

V Kotlin je async/await implementován pomocí coroutines — lehkých vláken jazyka. Funkce je označena klíčovým slovem suspend (obdoba Swift’s async). Pro spuštění se používá launch (fire-and-forget) nebo async (s výsledkem). Await se volá pro získání výsledku z async.

Dispatcher určuje, na jakém fondu vláken se korutina provádí: Dispatchers.Main pro UI, Dispatchers.IO pro síť/disk a Dispatchers.Default pro CPU-intenzivní úkoly. Structured Concurrency je zajištěna pomocí CoroutineScope — při zrušení scope jsou zrušeny všechny podřízené korutiny.

Podle údajů JetBrains (2025), 97 % Android aplikací v Google Play používá kotlinx.coroutines a 82 % z nich používá async/await pro síťové požadavky. Coroutines se staly de facto standardem pro asynchronní programování v Android. Kotlin Multiplatform také podporuje korutiny, což umožňuje používat společný asynchronní kód na Android, iOS a serverové části.

Příklady kódu s Async/Await ve Swift a Kotlin

Podívejme se na dva příklady pro každý jazyk: sekvenční načítání dat a paralelní požadavky s TaskGroup nebo async/await.

Swift: sekvenční async volání

await pozastavuje provádění do získání dat uživatele, poté — do získání přátel. Žádná vnořená uzavření.

swift
func loadProfile() async throws -> Profile {
    let user = try await api.fetchUser()
    let friends = try await api.fetchFriends(for: user.id)
    return Profile(user: user, friends: friends)
}

Swift: paralelní požadavky s TaskGroup

TaskGroup spouští úkoly paralelně a sbírá výsledky do pole. Pořadí výsledků se nemusí shodovat s pořadím spuštění.

swift
func loadParallel() async throws -> [String] {
    await withThrowingTaskGroup(of: String.self) { group in
        group.addTask { try await api.fetchName() }
        group.addTask { try await api.fetchEmail() }
        group.addTask { try await api.fetchAvatar() }
        var results = [String]()
        for try await value in group { results.append(value) }
        return results
    }
}

Kotlin: sekvenční volání s async/await

suspend funkce mohou volat jiné suspend funkce. Obdoba Swift: sekvenční volání.

kotlin
suspend fun loadProfile(): Profile {
    val user = api.fetchUser()
    val friends = api.fetchFriends(user.id)
    return Profile(user, friends)
}

Kotlin: paralelní požadavky s async/await

V Kotlin je paralelismu dosaženo pomocí coroutineScope s async pro každý požadavek.

kotlin
suspend fun loadParallel(): List<String> = coroutineScope {
    val name = async { api.fetchName() }
    val email = async { api.fetchEmail() }
    val avatar = async { api.fetchAvatar() }
    listOf(name.await(), email.await(), avatar.await())
}

Typické chyby a omezení Async/Await

Zapomenutý Task { } — asynchronní funkci nelze zavolat ze synchronního kontextu bez obalení do Task. Ve Swift to způsobí chybu při kompilaci. V Kotlin je vyžadováno spuštění přes lifecycleScope nebo viewModelScope. Pokus o zavolání suspend funkce z běžné funkce se nezkompiluje.

Nadměrné používání async bez potřeby

Ne každou funkci je třeba dělat asynchronní. CPU-intenzivní úkoly bez I/O nezískávají z async — je lepší je provádět na DispatchQueue s .userInitiated QoS. Async/Await je optimalizován pro I/O-bound operace: síť, disk, čekání.

Blokování hlavního vlákna přes .result

Použití .result na hlavním vlákně (synchronní čekání na výsledek async funkce) vede k blokování. Ve Swift Task.synchronousWait není doporučeno Apple. V Kotlin runBlocking na hlavním vlákně je antipattern, používejte lifecycleScope.

Únik Task při zrušení

Pokud Task není uložen do vlastnosti třídy, po opuštění kontextu je zrušen. Ve Swift je Task scoped — jeho životní cyklus je vázán na vytvářející kontext. Ukládejte Task do vlastnosti při potřebě dlouhotrvající operace.

Často kladené otázky

Čím se async/await liší od DispatchQueue?

Async/Await — jazyková konstrukce, která nevyžaduje vytváření front. DispatchQueue — to je systémové API pro správu vláken. Async/await je kompilován do state machine na úrovni jazyka, GCD — do syscall na úrovni OS.

Blokuje await vlákno?

Ne — await pozastavuje funkci, ale uvolňuje vlákno pro jiné úkoly. Po dokončení operace se funkce obnoví na libovolném dostupném vlákně z fondu.

Lze zrušit async úkol?

Ano — pomocí Task.cancel() ve Swift nebo Job.cancel() v Kotlin. Zrušení se šíří na všechny podřízené úkoly podle Structured Concurrency. Kód sám kontroluje příznak zrušení pomocí Task.isCancelled nebo ensureActive().

Co je MainActor ve Swift?

MainActor — to je actor, jehož vlastnosti a metody se vždy provádějí na hlavním vlákně. Označením funkce @MainActor zaručujete, že UI aktualizace probíhají na správném vlákně, čímž nahrazujete DispatchQueue.main.async.

Ve kterých jazycích je async/await?

Async/Await je dostupný v Swift (iOS 13+), Kotlin (přes kotlinx.coroutines), Dart (Flutter), JavaScript/TypeScript, Python, C#, Rust a Go (přes goroutines se syntaktickým cukrem).

Shrnutí

  • Async/Await — jazyková konstrukce pro lineární asynchronní kód bez callback hell
  • Swift Concurrency poskytuje Task, TaskGroup, Actor a Structured Concurrency
  • Kotlin coroutines používají suspend funkce, Dispatchers a korutinové scope
  • Pozastavení bez blokování — klíčový rozdíl async/await od vláken a front
  • Structured Concurrency zaručuje dokončení všech podřízených úkolů před nadřazeným
  • Async/Await vs GCD — první je upřednostňován pro nový kód, druhý pro legacy a low-level
  • MainActor ve Swift a Dispatchers.Main v Kotlin chrání UI vlákno před operacemi na pozadí

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é