Manejo de excepciones en Kotlin Coroutines | Autor: Jagdish Paryani | Ingeniería con corazón | Noviembre de 2021
Cubriremos todo tipo de funciones de constructor y manejo de excepciones para corrutinas.
Aquí lanzamos excepciones deliberadamente para probar la corrutina, en lugar de llamar a algunas API o hacer un trabajo en segundo plano que puede encontrar excepciones inesperadamente.
Veamos la función del generador de inicio con try-catch.
Por lo tanto, en el código anterior, puede ver que hemos iniciado una corrutina con una función de generador de inicio en el subproceso IO, y hemos lanzado una excepción dentro de la corrutina. En este caso, funciona como se esperaba porque la excepción se captura en el bloque de captura.
Pero cuando comenzamos otra corrutina en el bloque try-catch como se muestra a continuación,
En este caso, la excepción no se manejará y la aplicación se bloqueará. La razón de esto es que la corrutina interna se completa de manera anormal y la corrutina falla. Pero esto parece confuso.
Generalmente, cuando agregamos un bloque try-catch a cualquier función ordinaria en Java / Kotlin, cualquier excepción en el bloque try puede quedar atrapada en el bloque catch correspondiente. Entonces, ¿por qué no le pasa lo mismo a la corrutina?
Porque la función normal volverá a generar la excepción, pero es diferente en la corrutina.
Si el bloque try-catch no está en la corrutina, no volverá a generar la excepción, sino que se propagará al trabajo de la corrutina principal / corrutina de nivel superior que no puede manejarlo. Se llama al controlador de excepciones no detectado del hilo, lo que provoca el colapso de la aplicación .
Si la corrutina no usa la cláusula try-catch para manejar la excepción por sí misma, la excepción no se volverá a lanzar, por lo que no puede ser manejada por la cláusula try-catch externa. En cambio, la excepción es la «propagación hacia arriba en la jerarquía de trabajos».
Para manejar la situación anterior, necesitamos agregar CoroutineExceptionHandler, como se muestra en el siguiente código.
Cuando se utiliza CoroutineExceptionHandler, si una corrutina falla, todas las subcorutinas se cancelarán de forma predeterminada.
Para que CoroutineExceptionHandler surta efecto, debe instalarse en CoroutineScope o en una corrutina de nivel superior.
Ahora continúe usando async / await para manejar excepciones.
En async / await, si no llamamos al método await, no tendrá ningún efecto en nuestro programa y no generará una excepción. La razón de esto es que async devuelve un resultado retrasado, que se puede obtener del método await.
Aquí, en el código anterior, agregamos CoroutineExceptionHandler al alcance de la corrutina principal, y manejará todas las excepciones en ese alcance.
También podemos usar try-catch con async / await para manejar excepciones, pero para usar try-catch para manejar excepciones, necesitamos agregar un bloque try-catch en el método await en lugar de en el método asincrónico.Entonces, revisemos el código a continuación
De esta manera, podemos usar try-catch para manejar excepciones dentro del alcance de las corrutinas async / await.
Cuando discutimos el uso de corrutinas para try-catch al principio de este artículo, le dije que una corrutina fallida propagará su excepción hasta la jerarquía de trabajos en lugar de volver a lanzarla, por lo que el try-catch externo no es válido.
Sin embargo, cuando rodeamos una corrutina fallida con la función de alcance coroutineScope , sucede algo interesante
Ahora podemos usar la cláusula try-catch para manejar excepciones. Por lo tanto, la función de alcance coroutineScope vuelve a generar las excepciones de sus hijos fallidos, en lugar de propagarlos hacia arriba en la jerarquía de trabajos.
coroutineScope se usa principalmente para suspender funciones para lograr una «descomposición paralela». Estas funciones de suspensión volverán a generar la excepción de la corrutina en la que fallaron, por lo que podemos configurar nuestra lógica de manejo de excepciones en consecuencia.
La función de alcance coroutineScope vuelve a generar las excepciones de sus subcorutinas fallidas en lugar de propagarlas hacia arriba en la jerarquía de trabajos, lo que nos permite usar try-catch para manejar las excepciones de las corrutinas fallidas
Hemos visto que en todos los casos anteriores, si una corrutina falla, todas las demás corrutinas también fallarán. Si necesitamos otras corrutinas para continuar. Aquí, SupervisorScope puede resultar útil.
SupervisorScope crea un nuevo subámbito anidado independiente. No vuelve a generar la excepción como coroutineScope, ni propaga la excepción al alcance de la corrutina principal.
Podemos agregar CoroutineExceptionHandler o usar try-catch para manejar excepciones dentro de SupervisorScope.
Para async / await, necesitamos agregar try-catch para que otras corrutinas funcionen cuando fallan, como se muestra a continuación
Para withContext, podemos usar la misma forma que arriba para manejar excepciones, pero el constructor de corrutinas se cambiará y todo en withContext se ejecutará en orden.
Por lo tanto, de esta manera podemos manejar excepciones en las corrutinas de Kotlin.
Codificación feliz y manejo seguro de excepciones. ! !