Ποιους τρόπους διαχείρισης σφαλμάτων σε κορουτίνες γνωρίζετε;
sobes.tech AI
Απάντηση από AI
-
Χρήση των μπλοκ
try...catch. Τυπικός τρόπος διαχείρισης εξαιρέσεων. Λειτουργεί μέσα σε μια coroutine.// Εφαρμογή try-catch suspend fun fetchData(): String { return try { // Ενέργεια που μπορεί να ρίξει εξαίρεση throw Exception("Σφάλμα φόρτωσης δεδομένων") "Τα δεδομένα φορτώθηκαν επιτυχώς" } catch (e: Exception) { "Σφάλμα: ${e.message}" } }Το
try...catchδεν είναι κατάλληλο για τη διαχείριση ανεπεξέργαστων εξαιρέσεων που ρίχνονται από παιδικές coroutine που τρέχουν σε διαφορετικόCoroutineScope. -
CoroutineExceptionHandler. Πιάνει μη επεξεργασμένες εξαιρέσεις που ρίχνονται από coroutine, που ξεκινούν σε αυτό τοCoroutineScopeή στους παιδικούςCoroutineScopeτου.// CoroutineExceptionHandler val handler = CoroutineExceptionHandler { _, exception -> println("Πιασμένη εξαίρεση: $exception") } // Εφαρμογή του CoroutineExceptionHandler GlobalScope.launch(handler) { // Coroutine που μπορεί να ρίξει εξαίρεση throw Exception("Σφάλμα στη coroutine") }Το
CoroutineExceptionHandlerενεργοποιείται μόνο για εξαιρέσεις που δεν διαχειρίζονται από τον μηχανισμό δομημένου ανταγωνισμού. -
SupervisorJobκαιsupervisorScope. Σε αντίθεση με ένα συνηθισμένοJob, όταν μια παιδική coroutine με σφάλμα προκαλεί ακύρωση του γονικούJob, τοSupervisorJobδεν ακυρώνει τον γονικόJob. ΤοsupervisorScopeδημιουργεί έναCoroutineScopeμεSupervisorJob.// Χρήση του supervisorScope suspend fun loadMultipleData() = supervisorScope { val data1 = async { // Μπορεί να ρίξει εξαίρεση throw Exception("Σφάλμα στα δεδομένα 1") "Δεδομένα 1" } val data2 = async { "Δεδομένα 2" } // Διαχείριση εξαίρεσης για συγκεκριμένο async try { println("Αποτέλεσμα 1: ${data1.await()}") } catch (e: Exception) { println("Σφάλμα κατά τη φόρτωση δεδομένων 1: ${e.message}") } println("Αποτέλεσμα 2: ${data2.await()}") }Χρησιμοποιείται για ανεξάρτητες εργασίες παιδιών, όπου το σφάλμα ενός δεν πρέπει να επηρεάζει τα άλλα. Δεν αντικαθιστά το
try...catchή τοCoroutineExceptionHandler, αλλά αλλάζει τη συμπεριφορά διάδοσης εξαιρέσεων. -
Διάδοση εξαιρέσεων στη δομημένη ανταγωνιστικότητα. Από προεπιλογή, μια εξαίρεση σε παιδική coroutine ακυρώνει την γονική coroutine και όλους τους αδελφούς της.
// Παράδειγμα διάδοσης εξαίρεσης runBlocking { val job = launch { launch { // Παιδική coroutine 1 delay(100) throw Exception("Σφάλμα στην παιδική 1") } launch { // Παιδική coroutine 2 delay(200) println("Παιδική 2 ολοκληρώθηκε") } } try { job.join() } catch (e: Exception) { println("Πιάστηκε εξαίρεση στη γονική: $e") } }Αυτή είναι η βασική συμπεριφορά της δομημένης ανταγωνιστικότητας, που βοηθά στην αποφυγή διαρροών πόρων και καταστάσεων.
-
Χρήση του
asyncμεawait(). Οι εξαιρέσεις που ρίχνονται στοasyncδεν διαχέονται αυτόματα. Αποθηκεύονται μέσα στοDeferredκαι ρίχνονται μόνο κατά την κλήση τουawait().// Διαχείριση εξαιρέσεων με async/await suspend fun safeAsyncCall() = coroutineScope { val deferred = async { throw Exception("Σφάλμα στο async") "Αποτέλεσμα async" } try { val result = deferred.await() println("Αποτέλεσμα: $result") } catch (e: Exception) { println("Πιάστηκε εξαίρεση από το async: ${e.message}") } }Αυτό επιτρέπει την επιλεκτική διαχείριση σφαλμάτων για κάθε ασύγχρονη εργασία.
| Τρόπος | Σκοπός | Διαχειρίζεται uncaught; | Αλλάζει τη διάδοση; |
|---|---|---|---|
try...catch |
Διαχείριση εξαιρέσεων μέσα στη τρέχουσα coroutine | Όχι | Όχι |
CoroutineExceptionHandler |
Πιάσιμο μη διαχειριζόμενων εξαιρέσεων σε Scope | Ναι | Όχι |
SupervisorJob/Scope |
Αλλαγή συμπεριφοράς διάδοσης εξαιρέσεων | Όχι | Ναι |
| Δομημένη ανταγωνιστικότητα | Αυτόματη ακύρωση σε περίπτωση σφάλματος | Ναι | Ναι |
async + await() |
Απομακρυσμένη διάδοση εξαιρέσεων | Όχι | Ναι (μέχρι το await) |