Какви методи за обработка на грешки в корутините познавате?
sobes.tech AI
Отговор от AI
-
Използване на
try...catchблокове. Стандартен начин за обработка на изключения. Работи вътре в корутината.// Използване на try-catch suspend fun fetchData(): String { return try { // Операция, която може да хвърли изключение throw Exception("Грешка при зареждане на данни") "Данните са успешно заредени" } catch (e: Exception) { "Грешка: ${e.message}" } }try...catchне е подходящ за обработка на непотискани изключения, хвърлени от дъщерни корутини, стартирани в другCoroutineScope. -
CoroutineExceptionHandler. Хваща необработени изключения, хвърлени от корутините, които са стартирани в тозиCoroutineScopeили в неговите дъщерниCoroutineScope.// CoroutineExceptionHandler val handler = CoroutineExceptionHandler { _, exception -> println("Хванато изключение: $exception") } // Използване на CoroutineExceptionHandler GlobalScope.launch(handler) { // Корутината, която може да хвърли изключение throw Exception("Грешка в корутината") }CoroutineExceptionHandlerсе активира само за изключения, които не са обработени от механизма на структурирана конкуренция. -
SupervisorJobиsupervisorScope. За разлика от обикновенияJob, когато дъщерна корутина с грешка води до отменяне на родителския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, а по-скоро променя поведението при разпространение на изключения. -
Разпространение на изключения в структурирана конкуренция. По подразбиране, изключение в дъщерна корутина отменя родителската корутина и всички нейни сиблинги.
// Пример за разпространение на изключение runBlocking { val job = launch { launch { // Дъщерна корутина 1 delay(100) throw Exception("Грешка в дъщерната 1") } launch { // Дъщерна корутина 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}") } }Това позволява избирателна обработка на грешки за всяка асинхронна задача.
| Начин | Назначение | Обработва непотискани? | Променя разпространението? |
|---|---|---|---|
try...catch |
Обработка на изключения вътре в текущата корутина | Не | Не |
CoroutineExceptionHandler |
Хваща необработени изключения в Scope | Да | Не |
SupervisorJob/Scope |
Промяна на поведението при разпространение на изключения | Не | Да |
| Структурирана конкуренция | Автоматично отменяне при грешка | Да | Да |
async + await() |
Отложено разпространение на изключение | Не | Да (до await) |