async: ce este, Deferred și corutine paralele cum funcționează

Autor: IT Sectr Publicat: 2026-06-22 Timp de citire: 8 min

async — Coroutine Builder în Kotlin care lansează o corutină și returnează un obiect Deferred<T> pentru obținerea rezultatului unei operații asincrone. async permite executarea paralelă a mai multor sarcini și agregarea rezultatelor lor prin await(). Conform ghidului JetBrains, 2024, async este metoda preferată de organizare a calculelor paralele în corutine.

Principalele

  • async — constructor de corutine care returnează Deferred<T> cu rezultatul operației asincrone
  • Deferred — promisiune asincronă, care moștenește Job, cu metoda await() pentru obținerea rezultatului
  • async permite executarea paralelă a sarcinilor independente, reducând timpul total
  • await() — funcție suspend care întrerupe corutina până la obținerea rezultatului fără blocare
  • Concurvența structurată cu async garantează anularea tuturor sarcinilor paralele la eroare

Ce este async în Kotlin Coroutines?

async — este o funcție de extensie CoroutineScope care creează o corutină cu returnare de rezultat. Spre deosebire de launch, async returnează Deferred<T> — un obiect care reprezintă o valoare viitoare. Corutina lansată prin async se execută concurent cu alte corutine, permițând paralelizarea calculelor.

async este utilizat când rezultatul operației asincrone este necesar pentru procesare ulterioară: încărcarea datelor din mai multe surse, procesarea în lot a colecțiilor, cereri paralele la diverse API-uri. Deferred este creat imediat, iar rezultatul devine disponibil după finalizarea corutinei.

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

Sintaxa async și Deferred

Semnătura async este similară cu launch: aceiași parametri CoroutineContext, CoroutineStart și bloc suspend. Diferența constă în tipul returnat — Deferred<T> în loc de Job, unde T este tipul rezultatului returnat de ultima expresie a blocului.

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

Deferred<T> — interfață care moștenește Job și adaugă metodele await(), getCompleted(), getCompletionExceptionOrNull(). await() este o funcție suspend și poate fi apelată doar în interiorul unei corutine sau altei funcții suspend. getCompleted() — metodă neblocantă care aruncă o excepție dacă corutina nu s-a încheiat încă.

Sarcini paralele cu async

Principalul avantaj al async este posibilitatea de a lansa sarcini în paralel. În loc de așteptarea secvențială a fiecărei operații (timp total = suma timpurilor), async lansează corutinele simultan, reducând timpul total la timpul celei mai lungi operații.

Încărcarea paralelă a datelor

Scenariu tipic — încărcarea profilului utilizatorului, setărilor și istoricului comenzilor prin trei cereri async paralele. După finalizarea tuturor celor trei, rezultatele sunt combinate într-un singur model de date.

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

Funcția coroutineScope lansează corutinele copil și așteaptă finalizarea lor înainte de a returna rezultatul. Întregul bloc se execută paralel, nu secvențial.

Procesarea rezultatelor Deferred

Deferred suportă mai multe metode pentru lucrul cu rezultatul. Pe lângă await(), sunt disponibile metode pentru verificarea stării, obținerea valorii gata și agregarea mai multor Deferred prin funcțiile utilitare Kotlin Coroutines.

MetodăDescriereSuspend?
await()Întrerupe corutina până la obținerea rezultatuluiDa
getCompleted()Returnează rezultatul dacă corutina s-a încheiat (altfel Exception)Nu
getCompletionExceptionOrNull()Returnează excepția la eroare sau nullNu
isCompletedVerifică dacă corutina s-a încheiatNu

Pentru agregarea unei liste de Deferred se folosește awaitAll() — o funcție care întrerupe execuția până la finalizarea tuturor Deferred din colecție. Dacă cel puțin unul s-a încheiat cu eroare, awaitAll() aruncă o excepție.

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

Diferențele dintre async și launch

Alegerea între async și launch depinde de necesitatea rezultatului execuției corutinei. launch returnează Job și este potrivit pentru operații fire-and-forget, async returnează Deferred și este folosit pentru sarcini care returnează date. Din punct de vedere al sintaxei și parametrilor, constructorii sunt identici.

  • launch → Job (fără rezultat), async → Deferred<T> (are rezultat T)
  • launch — sarcini fire-and-forget (logare, cache, trimitere analitică)
  • async — calcule paralele (încărcare din mai multe API-uri, procesare în lot)
  • Ambele suportă concurvența structurată și parametrii CoroutineStart
  • await() este disponibil doar pentru Deferred, launch nu oferă rezultat

Regulă importantă: nu folosiți async pentru fire-and-forget. Dacă rezultatul corutinei nu este necesar, utilizați launch. async creează un overhead pentru crearea Deferred, care nu este justificat într-un astfel de scenariu.

Exemple async în dezvoltarea mobilă

În Android, async este utilizat pentru operații paralele în ViewModel și UseCases. Scenarii tipice: încărcarea simultană a profilului și a fluxului de știri, obținerea vremii de la mai multe servicii meteo, sincronizarea în lot a datelor cu serverul.

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

Se recomandă încapsularea grupului async în coroutineScope sau supervisorScope pentru izolarea erorilor. supervisorScope permite continuarea execuției celorlalte corutine async chiar și la eroare într-una dintre ele — util pentru operații necritice.

Întrebări frecvente

Se poate folosi async fără await?

Se poate, dar e inutil. async fără await() lansează corutina, dar rezultatul ei se pierde. Dacă rezultatul nu este necesar, utilizați launch — nu creează Deferred și este mai eficient din punct de vedere al memoriei și performanței.

Cum gestionează async excepțiile?

Excepția din interiorul async este salvată în Deferred. Apelul await() propagă această excepție. Pentru verificare fără propagare, utilizați getCompletionExceptionOrNull(). La utilizarea coroutineScope, eroarea anulează toate corutinele copil.

Ce este awaitAll în Kotlin Coroutines?

awaitAll() — o funcție de extensie pentru Iterable<Deferred<T>> care întrerupe corutina până la finalizarea tuturor Deferred. Returnează o listă de rezultate. Dacă cel puțin un Deferred se încheie cu eroare, propagă excepția și anulează restul.

Diferă async de GlobalScope.async?

Da. async este o funcție de extensie CoroutineScope, legată de scope. GlobalScope.async creează o corutină fără legătură cu ciclul de viață — se poate executa la nesfârșit. În Android, GlobalScope nu este recomandat din cauza riscului de scurgeri de memorie.

Câte corutine async pot fi lansate pentru cereri paralele?

Numărul este dictat de dispatcher: Dispatchers.IO suportă până la 64 de fire simultane, Dispatchers.Default — după numărul de nuclee CPU. Pentru operații masive, utilizați paralelism limitat prin Semaphore sau mapNotNull cu awaitAll.

Concluzii

  • async — constructor de corutine care returnează Deferred<T> pentru obținerea asincronă a rezultatului
  • Deferred moștenește Job și adaugă metodele await(), getCompleted(), getCompletionExceptionOrNull()
  • Executarea paralelă cu async reduce timpul total la durata celei mai lungi operații
  • awaitAll() — utilitar pentru așteptarea tuturor Deferred dintr-o colecție
  • coroutineScope — încapsulare recomandată pentru un grup de async cu garanție de anulare
  • Nu folosiți async pentru fire-and-forget — aplicați launch
  • În Android, async este utilizat pentru încărcări paralele în ViewModel cu viewModelScope

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