Kotlin可抛出异常协程链快速返回优化方案咨询
优化串行尝试多个suspend策略的实现
问题描述
有多个需尝试的策略,每个策略都是suspend函数,需要按串行顺序逐个执行,只要其中一个执行成功就返回。现有实现冗余,希望得到更简洁的方案。
原实现代码:
import kotlinx.coroutines.* import kotlin.random.Random suspend fun f1() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } suspend fun f2() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } fun main() = runBlocking { runCatching { f1() }.onSuccess { return@runBlocking } runCatching { f2() }.onSuccess { return@runBlocking } // 更多策略... }
优化方案
方案1:用循环遍历策略列表
把所有suspend策略函数放进一个列表,通过循环逐个执行,只要某个策略执行成功就立即返回,避免重复编写runCatching逻辑:
import kotlinx.coroutines.* import kotlin.random.Random suspend fun f1() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } suspend fun f2() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } // 新增更多策略示例 suspend fun f3() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } fun main() = runBlocking { val strategies = listOf(::f1, ::f2, ::f3) for (strategy in strategies) { runCatching { strategy() }.onSuccess { println("策略执行成功") return@runBlocking } } // 所有策略都失败的处理逻辑 println("所有策略执行失败") }
方案2:封装成通用函数
如果需要在多个地方复用这种“串行尝试直到成功”的逻辑,可以封装成一个通用suspend函数,提升复用性:
import kotlinx.coroutines.* import kotlin.random.Random suspend fun f1() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } suspend fun f2() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } suspend fun f3() = suspendCoroutine { cont -> if (Random.nextBoolean()) { cont.resume(Unit) } else { cont.resumeWithException(Exception()) } } /** * 串行执行多个suspend策略,直到第一个成功返回 * @param strategies 待尝试的策略列表 * @return 是否有策略执行成功 */ suspend fun tryStrategies(vararg strategies: suspend () -> Unit): Boolean { for (strategy in strategies) { if (runCatching { strategy() }.isSuccess) { return true } } return false } fun main() = runBlocking { val success = tryStrategies(::f1, ::f2, ::f3) if (success) { println("有策略执行成功") } else { println("所有策略执行失败") } }
额外优化:简化模拟函数
原代码中的f1、f2用suspendCoroutine模拟成功失败,可以简化成更简洁的写法(不影响核心逻辑):
suspend fun f1() { delay(100) // 模拟耗时操作 if (!Random.nextBoolean()) throw Exception("f1失败") } suspend fun f2() { delay(100) if (!Random.nextBoolean()) throw Exception("f2失败") }
内容的提问来源于stack exchange,提问作者bilabila
相关产品推荐
相关产品推荐

