You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:25:19