Kotlin Academy · Pelajaran

Propagasi Exception async/await

Pahami cara exception dari async menyebar dan kapan menggunakan try-await.

Pelajaran 3 dari 413 langkah

Propagasi Exception async/await adalah pelajaran Kotlin Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Kotlin Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Kotlin Academy mencakup 4 pelajaran total.

Operasi Asinkron Menyimpan Pengecualian

Tidak seperti launch, async menyimpan pengecualian dalam Deferred yang dikembalikan. Pengecualian tersebut hanya dilemparkan ulang saat Anda memanggil await().

import kotlinx.coroutines.*
fun main() = runBlocking {
    val deferred = async {
        throw RuntimeException("async error")
    }
    try {
        deferred.await()  // exception rethrown here
    } catch (e: RuntimeException) {
        println("Caught: ${e.message}")
    }
}

Pengecualian Tanpa await()

Jika Anda tidak pernah memanggil await(), pengecualian akan dibuang secara diam-diam bersama induk Job biasa. Sebaiknya gunakan supervisorScope + selalu tunggu hasilnya.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Exception stored in deferred, never retrieved:
    val d = async { throw RuntimeException("lost exception") }
    delay(100)  // d has failed — exception never surfaced
    println("d.isCancelled: ${d.isCancelled}")
}

Operasi Asinkron di Bawah coroutineScope

Di bawah coroutineScope biasa, jika tugas anak asinkron melemparkan pengecualian dan pengecualian tersebut diteruskan (tidak ditangkap), cakupan dan semua tugas saudaranya akan dibatalkan.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            val a = async { "A" }
            val b = async { throw RuntimeException("B failed") }
            println(a.await())
            println(b.await())  // propagates, cancels scope
        }
    } catch (e: RuntimeException) {
        println("Scope failed: ${e.message}")
    }
}

Operasi Asinkron di Bawah supervisorScope

Di bawah supervisorScope, pengecualian dari async TIDAK diteruskan ke tugas-tugas saudara. Setiap await() harus dibungkus secara terpisah.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val a = async { "A" }
        val b = async { throw RuntimeException("B failed") }
        println(a.await())
        try { println(b.await()) }
        catch (e: RuntimeException) { println("b failed: ${e.message}") }
    }
}

awaitAll untuk Beberapa Operasi Asinkron

awaitAll(d1, d2, d3) menunggu semua nilai tertunda. Jika salah satunya gagal, fungsi tersebut langsung melemparkan pengecualian dan membatalkan yang lainnya.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        val results = awaitAll(
            async { "result1" },
            async { throw RuntimeException("task 2 failed") },
            async { "result3" }
        )
        println(results)
    } catch (e: Exception) {
        println("awaitAll failed: ${e.message}")
    }
}

runCatching dengan Operasi Asinkron

Bungkus setiap await() dalam runCatching untuk mengumpulkan hasil dan kesalahan tanpa menghentikan proses pada kegagalan pertama.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val deferreds = listOf(
            async { "A" },
            async { throw RuntimeException("B") },
            async { "C" }
        )
        val results = deferreds.map { runCatching { it.await() } }
        results.forEach { println(it) }
    }
}

Tugas Paralel dengan Akumulasi Kesalahan

Kumpulkan semua kegagalan dari tugas asinkron yang berjalan paralel dan laporkan semuanya sekaligus, alih-alih gagal dengan segera.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val tasks = listOf("a", "b", "c")
    val results = supervisorScope {
        tasks.map { t ->
            async {
                if (t == "b") throw RuntimeException("b failed")
                t.uppercase()
            }
        }.map { runCatching { it.await() } }
    }
    val errors = results.filter { it.isFailure }
    val successes = results.mapNotNull { it.getOrNull() }
    println("Success: $successes, Errors: ${errors.size}")
}

Mempertahankan Jenis Pengecualian

Pengecualian yang dilemparkan di dalam async mempertahankan jenisnya. Tangkap jenis pengecualian tertentu saat await() untuk penanganan kesalahan yang tepat.

import kotlinx.coroutines.*
class NetworkException(msg: String) : RuntimeException(msg)
fun main() = runBlocking {
    val d = async { throw NetworkException("timeout") }
    try {
        d.await()
    } catch (e: NetworkException) {
        println("Network error: ${e.message}")
    } catch (e: Exception) {
        println("Other error: ${e.message}")
    }
}

Deferred.getCompleted() untuk Pemeriksaan Tanpa Penundaan

Setelah join(), gunakan getCompleted() untuk mengambil hasil secara sinkron. Fungsi tersebut akan melemparkan pengecualian jika nilai tertundanya gagal.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val d = async { 42 }
    d.join()  // wait without caring about result
    try {
        val result = d.getCompleted()  // synchronous — no suspend
        println("Result: $result")
    } catch (e: Exception) {
        println("Failed: ${e.message}")
    }
}

Konkurensi Terstruktur dan Operasi Asinkron

Dalam konkurensi terstruktur, nilai tertunda dari async selalu terhubung ke cakupan induknya. Saat cakupan dibatalkan, nilai tertunda tersebut juga dibatalkan—tidak ada tugas yatim.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val scope = CoroutineScope(SupervisorJob())
    val d = scope.async {
        delay(1000)
        "result"
    }
    scope.cancel()  // cancels d too
    try { d.await() }
    catch (e: CancellationException) { println("Cancelled as expected") }
}

Praktik Terbaik: Selalu Memanggil await

Selalu panggil await() untuk setiap nilai tertunda dari async, meskipun Anda tidak memerlukan hasilnya. Dengan begitu, pengecualian akan terlihat dan kegagalan diam-diam dapat dicegah.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val d = async {
            // do background work
            "done"
        }
        // Always await:
        val result = runCatching { d.await() }
        println(result)
    }
}

Pemeriksaan Singkat

Kapan pengecualian dari blok async { throw ... } muncul?

Ringkasan

async menyimpan pengecualian dalam Deferred; pengecualian tersebut muncul saat await(). Di bawah coroutineScope, propagasi membatalkan tugas-tugas saudara. Di bawah supervisorScope, setiap await harus menangani kegagalannya sendiri. Selalu tunggu setiap nilai tertunda.

Gratis untuk memulai

Belajar Kotlin dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
51
Pelajaran
203

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Propagasi Exception async/await” gratis?

Ya — teks lengkap “Propagasi Exception async/await” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Kotlin Academy, upgrade ke CoddyKit PRO. Kursus Kotlin Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Propagasi Exception async/await”?

Pahami cara exception dari async menyebar dan kapan menggunakan try-await. Kamu berlatih Kotlin Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Kotlin Academy?

Tidak diperlukan pengalaman sebelumnya. Kotlin Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Propagasi Exception async/await” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Kotlin Academy ini?

Ya. Setiap pelajaran Kotlin Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. SupervisorJob vs Job: Isolasi Kegagalan
  2. CoroutineExceptionHandler: Penangan Global yang Tidak Tertangkap
  3. Propagasi Exception async/await
  4. Merancang Arsitektur Coroutine yang Tangguh
← Kembali ke Kotlin Academy