I see multiple sources claiming that an exception happening inside an async{} block is not delivered anywhere and only stored in the Deferred
instance. The claim is that the exception remains "hidden" and only influences things outside at the moment where one will call await()
. This is often described as one of the main differences between launch{}
and async{}
. Here is an example.
异步代码中未捕获的异常存储在
According to this claim, at least the way I understand it, the following code should not throw, since no-one is calling await:
// throws
runBlocking {
async { throw Exception("Oops") }
}
然而,异常会被抛出.这也是here年前讨论过的,但通过阅读这篇文章,我无法真正理解why.
所以在我看来,当异步抛出时,一个"取消信号"在父作用域上传播,即使await()
没有被调用.正如上面引用的话所说,这个例外并没有真正隐藏起来,也没有悄悄地放弃.我的假设正确吗?
现在,如果我们通过SupervisorJob()
,代码会抛出not:
// does not throw
runBlocking {
async(SupervisorJob()) { throw Exception("Oops") }
}
This seems reasonable since supervisor job is meant to swallow failures.
And now comes the part I do not understand at all. If we pass Job()
, the code still runs without throwing, even though Job()
is supposed to propagate failures to its parent scope:
// does not throw. Why?
runBlocking {
async(Job()) { throw Exception("Oops") }
}
所以我的问题是,为什么不通过任何一项工作都会丢球,但通过任何一项工作或监督工作都不会丢球?