Veo varias fuentes que afirman que una excepción que ocurre dentro de un bloque async{} no se entrega en ninguna parte y solo se almacena en la instancia Deferred . El reclamo es que la excepción permanece "oculta" y solo influye en las cosas externas en el momento en que uno llamará await() . Esto a menudo se describe como una de las principales diferencias entre launch{} y async{} . Aquí hay un ejemplo .
Una excepción no detectada dentro del código asíncrono se almacena dentro del Diferido resultante y no se entrega en ningún otro lugar, se eliminará silenciosamente a menos que se procese
De acuerdo con este reclamo, al menos de la forma en que lo entiendo, el siguiente código no debería arrojar, ya que nadie está llamando en espera:
// throws runBlocking { async { throw Exception("Oops") } }Y, sin embargo, se lanza la excepción. Esto también se discute aquí , pero realmente no pude entender por qué al leer esto.
Entonces, me parece que cuando se lanza asíncrono, se propaga una "señal de cancelación" en el alcance principal, incluso si no se llama a await() . Es decir, la excepción realmente no permanece oculta, ni se elimina silenciosamente, como dice la cita anterior. ¿Es correcta mi suposición?
Ahora, si pasamos un SupervisorJob() , el código no arroja:
// does not throw runBlocking { async(SupervisorJob()) { throw Exception("Oops") } }Esto parece razonable ya que el trabajo de supervisor está destinado a tragar fallas.
Y ahora viene la parte que no entiendo nada. Si pasamos Job() , el código aún se ejecuta sin lanzar, aunque se supone que Job() propaga fallas a su alcance principal:
// does not throw. Why? runBlocking { async(Job()) { throw Exception("Oops") } }Entonces, mi pregunta es, ¿por qué pasar ningún trabajo arroja, pero pasar Job o SupervisorJob no arroja?