Sobes.tech
Middle

Ի՞նչ է տեղի ունենում կորուտինայի հետ, երբ տեղի է ունենում արտահայտություն։

sobes.tech AI

Պատասխան AI-ից

Երբ տեղի է ունենում արտակարգ իրավիճակ՝ ներսում կորուտինում, կախված արտակարգ իրավիճակի տեսակից (և dispatcher/կոնտեքստի կարգավորումներից), որոշվում է, թե ինչպես այն կթարգմանվի։

  • Անհետաձգելի արտակարգ իրավիճակ: Եթե արտակարգ իրավիճակը չհավաքվի ներսում կորուտինում, այն բարձրանում է կորուտինների հիերարխիայով մինչև ամենամոտ Job (կամ CoroutineScope)։ Կարգավորումը կախված է Job տեսակից.

    • Job: Դեպքում, երբ արտակարգ իրավիճակ է առաջանում դուստր կորուտինում, ծնողական Job-ը չեղյալ է հայտարարվում, ինչը հանգեցնում է նրա մյուս դուստր կորուտինների չեղյալ հայտարարմանը։ Արտակարգ իրավիճակը փոխանցվում է վերև։
    • SupervisorJob: SupervisorJob-ը չի չեղյալ հայտարարվում արտակարգ իրավիճակի դեպքում դուստր կորուտինում։ Միայն այն կորուտինն է չեղյալ հայտարարվում, որտեղ արտակարգ իրավիճակ է տեղի ունեցել։ Սա օգտակար է, երբ անհրաժեշտ է, որ մեկ դուստր գործի չեղյալ հայտարարման դեպքում մյուսները շարունակեն գործել։
    • CoroutineScope-ի հիմքը: Եթե արտակարգ իրավիճակը հասնում է CoroutineScope-ին (օրինակ, GlobalScope կամ CoroutineScope-ով ստեղծված առանց Job), այն փոխանցվում է CoroutineExceptionHandler-ին։ Դեպքում, երբ չի գրանցված handler, արտակարգ իրավիճակը գրանցվում է System.err-ում։
  • Հավաքված արտակարգ իրավիճակ: Եթե արտակարգ իրավիճակը բռնվում է try-catch բլոկով կորուտինում, այն տեղական է և կորուտինան շարունակում է գործել catch-ից հետո, եթե դա հնարավոր է։ Արտակարգ իրավիճակը չի փոխանցվում վերև։

  • Արտակարգ իրավիճակներ, կապված չեղարկման հետ (օրինակ, CancellationException): Այս արտակարգ իրավիճակները հատուկ են։ Դրանք օգտագործվում են կորուտինների չեղարկման մեխանիզմի համար և սովորաբար անտեսվում են արտակարգ իրավիճակների մշակողներից շատերի կողմից։ Դրանք չեն հանգեցնում Job-ի ֆատալային ձախողման։

  • async-ի մեջ արտակարգ իրավիճակներ: async-ով սկսված կորուտինը տեղադրում է արտակարգ իրավիճակը իր Deferred-ում։ Արտակարգ իրավիճակը փոխանցվում է միայն .await()-ի ժամանակ։ Մինչ այդ, արտակարգ իրավիճակը "թաքնված" է։

import kotlinx.coroutines.*

fun main() = runBlocking {
    val scope = CoroutineScope(SupervisorJob())

    scope.launch {
        try {
            println("Կորուտին 1 սկսվեց")
            delay(100)
            throw RuntimeException("Ինչ-որ բան սխալվեց Կորուտին 1-ում")
        } catch (e: Exception) {
            println("Հայտնաբերված արտակարգ իրավիճակ Կորուտին 1-ում: ${e.message}")
        }
    }

    scope.launch {
        println("Կորուտին 2 սկսվեց")
        delay(500)
        println("Կորուտին 2 ավարտվեց")
    }

    delay(1000) // Կատակում ենք, որպեսզի տեսնենք արդյունքը
    scope.cancel() // Չեղյալ ենք հայտարարում scope
}

Այս օրինակով, արտակարգ իրավիճակը Կորուտին 1-ում բռնվում է, և Կորուտին 2-ն շարունակում է գործել, քանի որ օգտագործվում է SupervisorJob։ Եթե փոխարենը օգտագործվեր սովորական Job, ապա արտակարգ իրավիճակը Կորուտին 1-ում կհանգեցներ Կորուտին 2-ի չեղարկմանը։