Async/Await: esența, funcțiile async și lucrul cu await

Autor: IT Sectr Publicat: 2026-03-16 Timp de citire: 8 min

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 — zahăr sintactic pentru cod asincron fără callback-uri imbricate
  • async marchează funcția ca asincronă și întreruptibilă
  • await întrerupe execuția funcției până la finalizarea operațiunii asincrone
  • Task în Swift creează o nouă unitate de lucru asincronă cu context
  • Structured Concurrency garantează că toate sarcinile secundare se finalizează înaintea celei părinte

Ce este Async/Await și programarea asincronă

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.

Principiul de funcționare: funcții întreruptibile

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.

Cum funcționează Async/Await: întrerupere și reluare

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.

  • Swift — compilatorul transpune funcția async în SIL cu runAsync coroutine frame
  • Kotlin — fiecare funcție suspend primește Continuation și delegă execuția dispatcher-ului
  • Ambele limbaje — eliberează firul la await, fără a-l bloca pe durata așteptării
  • Excepții — sunt propagate prin mecanisme standard (throws / try-catch)

Async/Await vs Callback-uri și GCD: compararea abordărilor

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.

AspectCallbackGCDAsync/Await
ImbricareProfundă (piramida morții)Medie (grupuri+notify)Liniară (plată)
Gestionarea erorilorPer-callbackManualăUnitară (try/catch)
AnulareManualăLimitatăTask.cancel()
Thread safetyManualăPrin serial queuePrin 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.

Swift Concurrency: Task, TaskGroup și Actor

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.

Structured Concurrency

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.

Async/Await în Kotlin cu corutine

Î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.

Exemple de cod cu Async/Await în Swift și Kotlin

Să luăm câte două exemple pentru fiecare limbaj: încărcarea secvențială a datelor și cererile paralele cu TaskGroup sau async/await.

Swift: apeluri async secvențiale

await întrerupe execuția până la obținerea datelor utilizatorului, apoi — până la obținerea prietenilor. Niciun closure imbricat.

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: cereri paralele cu TaskGroup

TaskGroup lansează sarcinile în paralel și colectează rezultatele într-un tablou. Ordinea rezultatelor poate să nu coincidă cu ordinea lansării.

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: apel secvențial cu async/await

Funcțiile suspend pot apela alte funcții suspend. Analog Swift: apeluri secvențiale.

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

Kotlin: cereri paralele cu async/await

În Kotlin, paralelismul se realizează prin coroutineScope cu async pentru fiecare cerere.

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

Erori tipice și limitări ale Async/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.

Utilizarea excesivă a async fără necesitate

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.

Blocarea firului principal prin .result

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.

Scurgerea Task la anulare

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

Cu ce diferă async/await de DispatchQueue?

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.

Blochează await firul?

Nu — await întrerupe funcția, dar eliberează firul pentru alte sarcini. După finalizarea operațiunii, funcția reia pe orice fir disponibil din pool.

Se poate anula o sarcină async?

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

Ce este MainActor în Swift?

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.

în ce limbaje există async/await?

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

  • Async/Await — construcție lingvistică pentru cod asincron liniar fără callback hell
  • Swift Concurrency oferă Task, TaskGroup, Actor și Structured Concurrency
  • Kotlin coroutines folosesc funcții suspend, Dispatchers și scope-uri de corutine
  • întreruperea fără blocare — diferența cheie dintre async/await și fire/cozi
  • Structured Concurrency garantează finalizarea tuturor sarcinilor secundare înaintea celei părinte
  • Async/Await vs GCD — primul preferat pentru cod nou, al doilea pentru legacy și low-level
  • MainActor în Swift și Dispatchers.Main în Kotlin protejează firul UI de operații de fundal

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.

Discutați proiectul

Citiți și