我正在尝试学习Kotlin协程,我有一些代码不理解,或者我需要更深入地研究它并进行实验。但是我遇到了一个问题,当在使用runBlocking
的协程作用域中使用launch
时,一段代码无法执行。
我创建了一个简单的get方法来执行GET请求:
suspend fun get(url: String): HttpResponse? {
try {
return client.get(url) {
headers {
append(HttpHeaders.Accept, "application/json")
}
}
} catch (e: Exception) {
log.error("Error: $e")
}
return null
}
然后在我的Main.kt中,我尝试使用以下代码调用它:
fun main(args: Array<String>) = runBlocking {
println("Kotlin Start")
val job = launch {
delay(2000L)
val response = get("https://some-domain.com")
response?.let {
println("Response: ${it.status}")
}
}
job.cancel()
println("Kotlin End")
}
它只给出了输出:
Kotlin Start
Kotlin End
所以我试着这样做只是为了好玩:
fun main(args: Array<String>) = runBlocking {
println("Kotlin Start")
get("https://some-domain.com")?.let {
println("Response: ${it.status}")
}
println("Kotlin End")
}
这一次它给了我:
Kotlin Start
Response: 200 OK
Kotlin End
这就是我想要的。这是一个有效的用例来使用launch
关键字还是我应该做最后一个例子?我应该使用runBlocking
吗?老实说,有点困惑,所以一些澄清将是有益的。
2条答案
按热度按时间wqnecbli1#
很难回答是否应该使用
launch()
,因为这取决于您的需要。launch()
用于需要并发执行多个操作的情况。例如,如果您需要执行两个请求,并且您在没有launch()
的情况下将它们一个接一个地放置,那么第二个请求将仅在第一个请求完成之后才开始执行。如果您将它们放在单独的launch()
块中,它们将同时并发运行。在你的第一个例子中,你在启动作业后立即取消了它,所以很可能它甚至没有机会开始执行。老实说,我不知道为什么你会期望一个不同的行为。如果我们取消了一些东西,那么看到它仍然在运行会相当惊讶。
ax6ht2ek2#
这是使用launch关键字的有效用例吗?还是应该使用最后一个示例?
嗯,一个做你想做的,另一个不做。所以我会说“不”,这不是一个有效的用例(因为它没有做你想做的)和“是”,你应该做最后一个例子(因为它做你想做的)。
我应该使用runBlocking吗?
是的,如果有意义的话。不,如果没有。
runBlocking被设计成“常规”代码和协程之间的桥梁,因此您可以在其他同步代码中运行协程。
老实说有点困惑,所以一些澄清会很有帮助。
你需要问一个更具体的问题,你对什么感到困惑,需要澄清。如果你通常对协程感到困惑,那么你最好的选择是花时间在文档和网络上无限数量的内容上解释这个主题。