async: ano ito, Deferred at mga parallel na coroutine kung paano gumagana

May-akda: IT Sectr Nai-publish: 2026-06-22 Oras ng pagbabasa: 8 min

async — Coroutine Builder sa Kotlin na nagpapatakbo ng coroutine at nagbabalik ng Deferred<T> na object para makuha ang resulta ng asynchronous na operasyon. Pinapayagan ng async ang parallel na pagpapatupad ng maraming gawain at pagsasama-sama ng kanilang mga resulta sa pamamagitan ng await(). Ayon sa gabay ng JetBrains, 2024, ang async ay ang mas gustong paraan ng pag-oorganisa ng parallel computations sa mga coroutine.

Mga Pangunahing Punto

  • async — tagabuo ng coroutine na nagbabalik ng Deferred<T> na may resulta ng asynchronous na operasyon
  • Deferred — asynchronous na pangako, nagmamana ng Job, na may paraang await() para makuha ang resulta
  • async ay nagpapahintulot ng parallel na pagpapatupad ng mga independiyenteng gawain, binabawasan ang kabuuang oras
  • await() — suspend-function na nagpapatigil sa coroutine hanggang makuha ang resulta nang hindi binablock
  • Naka-estrukturang konkurensiya sa async ay ginagarantiyang kanselahin ang lahat ng parallel na gawain kapag may error

Ano ang async sa Kotlin Coroutines?

async — ay isang extension function ng CoroutineScope na lumilikha ng coroutine na may pagbabalik ng resulta. Hindi tulad ng launch, ang async ay nagbabalik ng Deferred<T> — isang bagay na kumakatawan sa isang hinaharap na halaga. Ang coroutine na pinatakbo sa pamamagitan ng async ay isinasagawa nang konkurent sa iba pang mga coroutine, na nagpapahintulot ng parallelisasyon ng mga computation.

Ang async ay ginagamit kapag ang resulta ng asynchronous na operasyon ay kailangan para sa karagdagang pagproseso: pagkarga ng data mula sa maraming source, batch processing ng mga koleksyon, parallel na mga kahilingan sa iba't ibang API. Deferred ay nilikha agad, at ang resulta ay magiging available pagkatapos matapos ang coroutine.

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

Syntax ng async at Deferred

Ang syntax ng async ay katulad ng launch: parehong mga parameter na CoroutineContext, CoroutineStart at suspend-block. Ang pagkakaiba ay sa uri na ibinabalik — Deferred<T> sa halip na Job, kung saan ang T ay ang uri ng resultang ibinalik ng huling expression ng block.

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

Deferred<T> — interface na nagmamana ng Job at nagdaragdag ng mga paraang await(), getCompleted(), getCompletionExceptionOrNull(). Ang await() ay isang suspend-function at maaari lamang tawagin sa loob ng coroutine o ibang suspend-function. Ang getCompleted() — ay isang non-blocking na paraan na nagtatapon ng exception kung hindi pa tapos ang coroutine.

Mga parallel na gawain gamit ang async

Ang pangunahing bentahe ng async ay ang kakayahang magpatakbo ng mga gawain nang parallel. Sa halip na sunud-sunod na paghihintay sa bawat operasyon (kabuuang oras = kabuuan ng mga oras), ang async ay nagpapatakbo ng mga coroutine nang sabay-sabay, binabawasan ang kabuuang oras sa oras ng pinakamahabang operasyon.

Parallel na pagkarga ng data

Karaniwang senaryo — pagkarga ng profile ng user, kanyang mga setting, at kasaysayan ng order na may tatlong parallel na async na kahilingan. Pagkatapos matapos ang lahat ng tatlo, ang mga resulta ay pinagsama sa iisang modelo ng data.

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

Ang function na coroutineScope ay nagpapatakbo ng mga child coroutine at naghihintay sa kanilang pagkumpleto bago ibalik ang resulta. Ang buong block ay isinasagawa nang parallel, hindi sunud-sunod.

Pagproseso ng mga resulta ng Deferred

Sinusuportahan ng Deferred ang ilang mga paraan para sa pagtatrabaho sa resulta. Bukod sa await(), may mga paraan para sa pagsusuri ng status, pagkuha ng handa na halaga, at pagsasama-sama ng maraming Deferred sa pamamagitan ng mga utility function ng Kotlin Coroutines.

ParaanPaglalarawanSuspend?
await()Pinipigilan ang coroutine hanggang makuha ang resultaOo
getCompleted()Ibinabalik ang resulta kung tapos na ang coroutine (kung hindi ay Exception)Hindi
getCompletionExceptionOrNull()Ibinabalik ang exception kapag may error o nullHindi
isCompletedSinusuri kung tapos na ang coroutineHindi

Para sa pagsasama-sama ng listahan ng Deferred ay ginagamit ang awaitAll() — isang function na pumipigil sa pagpapatupad hanggang sa matapos ang lahat ng Deferred sa koleksyon. Kung kahit isa ay natapos na may error, ang awaitAll() ay nagtatapon ng exception.

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

Mga pagkakaiba sa pagitan ng async at launch

Ang pagpili sa pagitan ng async at launch ay depende sa kung kailangan ang resulta ng pagpapatupad ng coroutine. launch ay nagbabalik ng Job at angkop para sa fire-and-forget na mga operasyon, async ay nagbabalik ng Deferred at ginagamit para sa mga gawaing nagbabalik ng data. Sa mga tuntunin ng syntax at parameter, ang mga tagabuo ay magkapareho.

  • launch → Job (walang resulta), async → Deferred<T> (may resulta T)
  • launch — fire-and-forget na mga gawain (pag-log, pag-cache, pagpapadala ng analytics)
  • async — parallel computations (pagkarga mula sa maraming API, batch processing)
  • Parehong sumusuporta sa naka-estrukturang konkurensiya at mga parameter ng CoroutineStart
  • Ang await() ay available lamang para sa Deferred, ang launch ay hindi nagbibigay ng resulta

Mahalagang tuntunin: huwag gumamit ng async para sa fire-and-forget. Kung hindi kailangan ang resulta ng coroutine, gamitin ang launch. Ang async ay lumilikha ng overhead para sa paggawa ng Deferred, na hindi makatwiran sa ganitong senaryo.

Mga halimbawa ng async sa mobile development

Sa Android, ang async ay ginagamit para sa parallel na mga operasyon sa loob ng ViewModel at UseCases. Mga karaniwang senaryo: sabay-sabay na pagkarga ng profile at news feed, pagkuha ng panahon mula sa maraming serbisyo ng panahon, batch synchronization ng data sa server.

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

Inirerekomenda na balutin ang grupo ng async sa coroutineScope o supervisorScope para sa paghihiwalay ng error. Pinapayagan ng supervisorScope ang pagpapatuloy ng pagpapatupad ng iba pang mga async coroutine kahit na may error sa isa sa mga ito — kapaki-pakinabang para sa hindi kritikal na mga operasyon.

Mga Madalas Itanong

Maaari bang gamitin ang async nang walang await?

Maaari, ngunit walang saysay. Ang async na walang await() ay nagpapatakbo ng coroutine, ngunit ang resulta nito ay nawawala. Kung hindi kailangan ang resulta, gamitin ang launch — hindi ito lumilikha ng Deferred at mas mahusay sa memorya at pagganap.

Paano hinahawakan ng async ang mga exception?

Ang exception sa loob ng async ay nai-save sa Deferred. Ang pagtawag sa await() ay nagtatapon ng exception na ito. Para suriin nang hindi nagtatapon, gamitin ang getCompletionExceptionOrNull(). Kapag gumagamit ng coroutineScope, kinakansela ng error ang lahat ng child coroutine.

Ano ang awaitAll sa Kotlin Coroutines?

awaitAll() — isang extension function para sa Iterable<Deferred<T>> na pumipigil sa coroutine hanggang matapos ang lahat ng Deferred. Ibinabalik ang listahan ng mga resulta. Kung kahit isang Deferred ay natapos na may error, itinatapon nito ang exception at kinakansela ang iba pa.

Iba ba ang async sa GlobalScope.async?

Oo. Ang async ay isang extension function ng CoroutineScope, nakatali sa scope. GlobalScope.async ay lumilikha ng coroutine na walang koneksyon sa lifecycle — maaari itong tumakbo nang walang katapusan. Sa Android, ang GlobalScope ay hindi inirerekomenda dahil sa panganib ng pagtagas ng memorya.

Ilang async coroutine ang maaaring patakbuhin para sa parallel na mga kahilingan?

Ang bilang ay idinidikta ng dispatcher: Sinusuportahan ng Dispatchers.IO ang hanggang 64 na sabay-sabay na thread, Dispatchers.Default — batay sa bilang ng CPU cores. Para sa malawakang operasyon, gumamit ng limitadong paralelismo sa pamamagitan ng Semaphore o mapNotNull na may awaitAll.

Buod

  • async — tagabuo ng coroutine na nagbabalik ng Deferred<T> para sa asynchronous na pagkuha ng resulta
  • Deferred ay nagmamana ng Job at nagdaragdag ng mga paraang await(), getCompleted(), getCompletionExceptionOrNull()
  • Parallel na pagpapatupad sa async ay binabawasan ang kabuuang oras sa tagal ng pinakamahabang operasyon
  • awaitAll() — utility para maghintay ng lahat ng Deferred sa koleksyon
  • coroutineScope — inirerekomendang wrapper para sa grupo ng async na may garantiya ng pagkansela
  • Huwag gumamit ng async para sa fire-and-forget — gamitin ang launch
  • Sa Android, ang async ay ginagamit para sa parallel na pagkarga sa ViewModel na may viewModelScope

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din