我有一个在第二个元素上抛出异常的简单流程:
private val log = LoggerFactory.getLogger("test")
fun main() = runBlocking {
flowOf(1, 2, 3)
.onCompletion { log.info("Flow completed${if (it == null) "" else " exceptionally: ${it.message}"}") }
.buffer()
.map { throwingMapper(it) }
.catch { log.error("Exception thrown") }
.collect { log.info(it) }
}
}
fun throwingMapper(it: Int): String {
if (it == 2) {
throw Exception("Test exception")
}
return "$it-mapped"
}
当我执行这段代码时,我得到以下输出 - 流程完成无一例外:
2021-04-09 12:35:00.875 [main] INFO - test:31 - Flow completed
2021-04-09 12:35:00.904 [main] INFO - test:133 - 1-mapped
2021-04-09 12:35:00.915 [main] ERROR - test:34 - Exception thrown
但是,当我在 map
之前移动 buffer
运算符时:
flowOf(1, 2, 3)
.onCompletion { log.info("Flow completed${if (it == null) "" else " exceptionally: ${it.message}"}") }
.map { throwingMapper(it) }
.buffer()
.catch { log.error("Exception thrown") }
.collect { log.info(it) }
产生以下输出并完成流程例外:
2021-04-09 12:38:35.982 [main] INFO - test:31 - Flow completed exceptionally: Test exception
2021-04-09 12:38:36.024 [main] ERROR - test:34 - Exception thrown
为什么在第一种情况下流程会无异常地完成? buffer
是否会默默吞下下游异常?或者它是否在内部创建了一个新的流程?如果是这样,是否有一些保留原始例外?
答案 0 :(得分:1)
正如此方法的 documentation 所述:
<块引用><!DOCTYPE html>
<html>
<head>
<title>Title</title>
<meta charset="utf-8">
</head>
<body>
<figure class="figure" id="other figure">
<image src="https://p.bigstockphoto.com/GeFvQkBbSLaMdpKXF1Zv_bigstock-Aerial-View-Of-Blue-Lakes-And--227291596.jpg" width="100%" style="max-height: 70vh"></image>
<figcaption>I am a figcaption.</figcaption>
</figure>
<float class="figure" id="my figure">
<image src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1200px-Image_created_with_a_mobile_phone.png" width="100%" style="max-height: 70vh"></image>
<caption>I am a caption</caption>
<figcaption>I am a figcaption 2.</figcaption>
<p>1</p>
<p>2</p>
</float>
<script>
console.log(document.getElementsByTagName("float")); // Works fine with this custom tag
console.log(document.getElementsByTagName("figure")); // Works fine
console.log(document.getElementsByTagName("image")); // Fails, returns empty list with NON custom tag
console.log(document.getElementsByTagName("caption")); // Fails, returns empty list
console.log(document.getElementsByTagName("figcaption")); // Works fine
console.log(document.getElementsByTagName("p")); // Works fine
</script>
</body>
</html>
运算符在执行期间为其应用的流创建一个单独的协程。
[...]
buffer
之前的代码将在一个单独的新协程 [...] 中与 [调用此代码的协程] 同时执行。
在第一种情况下,流程无异常完成,因为抛出异常的方法和捕获异常的方法都放在 buffer
的一侧,因此它们在同一个协程中执行。
协程之间使用通道将协程 P 发出的元素发送到协程 Q。
我认为不可能通过 buffer
发送异常,因此您可能需要在 Channel
之前和之后定义两个 catch
处理程序(如果您希望异常是两部分都抛出)。