Async/Await — este o pereche de cuvinte cheie pentru scrierea codului asincron în stil sincron, disponibilă în Swift de la iOS 13 și în Kotlin cu corutine. Potrivit Apple Swift Documentation, 2026, Async/Await înlocuiește lanțurile de callback-uri și GCD, făcând codul asincron liniar și lizibil. Cuvântul cheie async marchează funcția ca asincronă, iar await îi întrerupe execuția până la primirea rezultatului.
Principalele idei
Async/Await — este o construcție lingvistică care permite scrierea codului asincron la fel de liniar ca cel sincron. În Swift a apărut în iOS 13 / macOS 10.15 odată cu framework-ul Swift Concurrency. În Kotlin, async/await este disponibil prin biblioteca de corutine (kotlinx.coroutines) începând cu versiunea 1.3.
Înainte de apariția async/await, codul asincron se baza pe callback-uri, GCD sau RxSwift. Lanțurile de callback-uri imbricate duceau la callback hell — o imbricare profundă care complică citirea și depanarea. Async/Await rezolvă această problemă, permițând funcțiilor asincrone să se „întrerupă” în punctele await și să reia după primirea rezultatului.
Potrivit Google (2025), utilizarea async/await în Kotlin reduce numărul de linii de cod asincron cu 40–60% față de abordarea bazată pe callback-uri. În Swift, adoptarea Swift Concurrency a atins 68% între aplicațiile publicate în 2025. iOS 16 a adăugat suport pentru Swift Concurrency în UIKit, SwiftUI și Foundation, făcând async/await un instrument standard pentru toate proiectele noi Apple.
Diferența cheie dintre async/await și firele de execuție — întreruperea fără blocare. Când funcția întâlnește await, se întrerupe, eliberând firul curent pentru alte sarcini. După finalizarea operațiunii asincrone, funcția reia pe același fir sau pe altul. Aceasta se numește multitasking cooperativ.
Funcția async este compilată într-o mașină de stări — un automat finit care gestionează stările de execuție. În punctul await, compilatorul salvează contextul (variabile locale, adresa de returnare) și transferă controlul runtime-ului. Când rezultatul este gata, runtime restaurează contextul și continuă execuția.
În Swift, această mașină de stări este implementată la nivelul compilatorului SIL (Swift Intermediate Language). În Kotlin — prin mecanismul Continuation Passing Style (CPS): fiecare funcție suspend primește un parametru ascuns Continuation, prin care este returnat rezultatul. Ambele abordări garantează reluarea sigură fără scurgeri de memorie.
Abordarea prin callback-uri necesită transmiterea unui closure care este apelat după finalizarea operațiunii. La trei cereri succesive, rezultă trei niveluri de imbricare cu gestionarea erorilor la fiecare nivel. Async/Await transformă aceleași trei cereri în trei linii succesive cu un singur bloc catch.
GCD (DispatchQueue) rezolvă problema callback hell prin cozi seriale și DispatchGroup, dar rămâne verbose. Pentru o sarcină simplă — încărcarea user, apoi friends, apoi UI — necesită crearea de cozi, grupuri și blocuri notify. Async/Await execută aceeași sarcină cu trei linii într-o singură funcție.
| Aspect | Callback | GCD | Async/Await |
|---|---|---|---|
| Imbricare | Profundă (piramida morții) | Medie (grupuri+notify) | Liniară (plată) |
| Gestionarea erorilor | Per-callback | Manuală | Unitară (try/catch) |
| Anulare | Manuală | Limitată | Task.cancel() |
| Thread safety | Manuală | Prin serial queue | Prin MainActor |
Potrivit Apple WWDC 2024, Swift Concurrency async/await este abordarea recomandată pentru codul nou. GCD rămâne pentru integrarea cu bibliotecile C și scenarii specifice de procesare low-level a firelor.
Task — este unitatea de bază a muncii asincrone în Swift. Task-ul este creat în contextul unui actor existent sau pe un fir arbitrar. În interiorul Task-ului se pot apela funcții async prin await. TaskGroup permite lansarea mai multor sarcini secundare în paralel și colectarea rezultatelor lor — un analog al DispatchGroup pe steroizi.
Actor — un tip de referință thread-safe care își protejează starea de cursele de date. Compilatorul garantează că accesul la proprietățile actorului este posibil doar prin apeluri async sau în cadrul izolării actorului. Actor înlocuiește serial DispatchQueue pentru protejarea stării partajate mutabile fără blocări manuale.
Principiul Structured Concurrency spune: fiecare sarcină asincronă are un părinte, iar părintele nu se finalizează până când nu se finalizează toți copiii săi. Dacă sarcina A lansează Task { await B() }, atunci A așteaptă B. Aceasta previne scurgerile de sarcini și asigură un ciclu de viață previzibil.
În Kotlin, async/await este implementat prin coroutines — fire ușoare ale limbajului. Funcția este marcată cu cuvântul cheie suspend (analogul lui async din Swift). Pentru lansare se folosește launch (fire-and-forget) sau async (cu rezultat). Await este apelat pentru obținerea rezultatului de la async.
Dispatcher determină pe ce pool de fire se execută corutina: Dispatchers.Main pentru UI, Dispatchers.IO pentru rețea/disc și Dispatchers.Default pentru sarcini intensive CPU. Structured Concurrency este asigurată prin CoroutineScope — la anularea scope-ului, toate corutinele secundare sunt anulate.
Potrivit JetBrains (2025), 97% dintre aplicațiile Android din Google Play folosesc kotlinx.coroutines, iar 82% dintre ele aplică async/await pentru cererile de rețea. Corutinele au devenit standardul de facto pentru programarea asincronă în Android. Kotlin Multiplatform suportă de asemenea corutinele, permițând utilizarea codului asincron comun pe Android, iOS și partea de server.
Să luăm câte două exemple pentru fiecare limbaj: încărcarea secvențială a datelor și cererile paralele cu TaskGroup sau async/await.
await întrerupe execuția până la obținerea datelor utilizatorului, apoi — până la obținerea prietenilor. Niciun closure imbricat.
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)
}
TaskGroup lansează sarcinile în paralel și colectează rezultatele într-un tablou. Ordinea rezultatelor poate să nu coincidă cu ordinea lansării.
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
}
}
Funcțiile suspend pot apela alte funcții suspend. Analog Swift: apeluri secvențiale.
suspend fun loadProfile(): Profile {
val user = api.fetchUser()
val friends = api.fetchFriends(user.id)
return Profile(user, friends)
}
În Kotlin, paralelismul se realizează prin coroutineScope cu async pentru fiecare cerere.
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())
}
Task { } uitat — funcția asincronă nu poate fi apelată din context sincron fără a fi înfășurată în Task. în Swift, aceasta se compilează cu eroare. în Kotlin, este necesară lansarea prin lifecycleScope sau viewModelScope. încercarea de a apela o funcție suspend dintr-o funcție obișnuită nu se va compila.
Nu orice funcție trebuie făcută asincronă. Sarcinile intensive CPU fără I/O nu beneficiază de async — este mai bine să fie executate pe DispatchQueue cu .userInitiated QoS. Async/Await este optimizat pentru operații I/O-bound: rețea, disc, așteptare.
Utilizarea .result pe firul principal (așteptarea sincronă a rezultatului funcției async) duce la blocare. În Swift, Task.synchronousWait nu este recomandat de Apple. În Kotlin, runBlocking pe firul principal este un anti-pattern — folosiți lifecycleScope.
Dacă Task nu este salvat într-o proprietate a clasei, după ieșirea din context el este anulat. În Swift, Task este scoped — ciclul său de viață este legat de contextul creator. Salvați Task-ul într-o proprietate atunci când este necesară o operație de lungă durată.
întrebări frecvente
Async/Await — este o construcție lingvistică care nu necesită crearea de cozi. DispatchQueue — este un API de sistem pentru gestionarea firelor. Async/await este compilat într-o mașină de stări la nivel de limbaj, GCD — în syscall la nivel de sistem de operare.
Nu — await întrerupe funcția, dar eliberează firul pentru alte sarcini. După finalizarea operațiunii, funcția reia pe orice fir disponibil din pool.
Da — prin Task.cancel() în Swift sau Job.cancel() în Kotlin. Anularea se propagă la toate sarcinile secundare conform Structured Concurrency. Codul însuși verifică flag-ul de anulare prin Task.isCancelled sau ensureActive().
MainActor — este un actor ale cărui proprietăți și metode se execută întotdeauna pe firul principal. Marcând o funcție cu @MainActor, garantați că actualizările UI au loc pe firul corect, înlocuind DispatchQueue.main.async.
Async/Await este disponibil în Swift (iOS 13+), Kotlin (prin kotlinx.coroutines), Dart (Flutter), JavaScript/TypeScript, Python, C#, Rust și Go (prin goroutines cu zahăr sintactic).
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și