0Pricing
Kotlin Academy · Lektion

Exception-Weitergabe bei async/await

Verstehen Sie, wie Exceptions aus async weitergegeben werden und wann try-await verwendet wird.

Exception-Weitergabe bei async/await ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

async speichert Ausnahmen

Anders als launch speichert async die Ausnahme im zurückgegebenen Deferred. Sie wird erst erneut ausgelöst, wenn Sie await() aufrufen.

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

Ausnahme ohne await()

Wenn Sie await() nie aufrufen, wird die Ausnahme bei einem regulären Job-Parent stillschweigend verworfen. Verwenden Sie bevorzugt supervisorScope + warten Sie immer mit await.

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

async unter coroutineScope

Unter einem regulären coroutineScope bricht eine Ausnahme aus einer untergeordneten async-Coroutine, die weitergegeben und nicht abgefangen wird, den Scope und alle Geschwister-Coroutines ab.

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

async unter supervisorScope

Unter supervisorScope werden Ausnahmen aus async NICHT an Geschwister-Coroutines weitergegeben. Jeder Aufruf von await()` muss einzeln verpackt werden.

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 für mehrere Async-Aufgaben

awaitAll(d1, d2, d3) wartet auf alle Deferreds. Wenn eines fehlschlägt, wird sofort eine Ausnahme ausgelöst und die anderen werden abgebrochen.

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 mit async

Verpacken Sie jeden Aufruf von await() in runCatching, um Ergebnisse und Fehler zu sammeln, ohne die Verarbeitung beim ersten Fehler abzubrechen.

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

Parallele Aufgaben mit Fehlerakkumulation

Sammeln Sie alle Fehler aus parallelen async-Aufgaben und melden Sie sie gemeinsam, anstatt die Verarbeitung beim ersten Fehler abzubrechen.

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

Erhaltung des Ausnahmetyps

Ausnahmen, die innerhalb von async ausgelöst werden, behalten ihren Typ. Fangen Sie bei await() den spezifischen Ausnahmetyp ab, um den Fehler präzise zu behandeln.

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() für eine nicht blockierende Prüfung

Verwenden Sie nach join() getCompleted(), um das Ergebnis synchron abzurufen. Die Methode löst eine Ausnahme aus, wenn das Deferred fehlgeschlagen ist.

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

Strukturierte Nebenläufigkeit und async

Bei strukturierter Nebenläufigkeit ist ein async-Deferred immer mit seinem übergeordneten Scope verknüpft. Wenn der Scope abgebrochen wird, wird auch das Deferred abgebrochen – es gibt keine verwaisten Aufgaben.

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

Best Practice: Immer await aufrufen

Rufen Sie für jedes async-Deferred immer await() auf, auch wenn Sie das Ergebnis nicht benötigen. Dadurch werden Ausnahmen sichtbar und stille Fehler verhindert.

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

Kurze Überprüfung

Wann wird die Ausnahme aus einem Block async { throw ... } sichtbar?

Zusammenfassung

async speichert Ausnahmen im Deferred; sie werden bei await() sichtbar. Unter coroutineScope bricht die Weitergabe Geschwister-Coroutines ab. Unter supervisorScope muss jeder Aufruf von await den eigenen Fehler behandeln. Warten Sie immer auf jedes Deferred.

Häufig gestellte Fragen

Ist die Lektion „Exception-Weitergabe bei async/await“ kostenlos?

Ja — der vollständige Text von „Exception-Weitergabe bei async/await“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Exception-Weitergabe bei async/await“?

Verstehen Sie, wie Exceptions aus async weitergegeben werden und wann try-await verwendet wird. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Exception-Weitergabe bei async/await“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. SupervisorJob vs. Job: Fehlerisolierung
  2. CoroutineExceptionHandler: globaler Handler für unbehandelte Exceptions
  3. Exception-Weitergabe bei async/await
  4. Robuste Coroutine-Architekturen entwerfen
← Zurück zu Kotlin Academy