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

如何用Kotlin函数式编程循环调用API直到获取非Canceled响应?

协程环境下用函数式风格实现API轮询直到状态非Canceled

问题描述

我调用的API会返回类似BW3511,HGP,ITP,Canceled,32格式的文本,需要持续调用该API直到返回的状态不为"Canceled"。目前已有以下代码:

获取航班数据的协程代码

val flightResponse = async {
    println("Started fetching Flight info.")
    client.get<String>(FLIGHT_ENDPOINT).also {
            println("Finished fetching Flight info.")
    }
}

其中client.get只能在coroutineScope体内调用,flightResponse的类型为Deferred<String>。

判断状态是否为Canceled的函数

fun isCanceled(
        flightResponse: String
    ) : Boolean {
        val (_, _, _, status, _) = flightResponse.split(",")
        return status == "Canceled"
    }

我尝试过使用takeIf,但它需要至少一个非空结果,想请教如何用函数式编程风格重复调用client.get<String>(FLIGHT_ENDPOINT)直到条件满足?

解决方案

可以借助generateSequence实现惰性序列生成,配合协程的async和await,以函数式风格完成轮询逻辑:

coroutineScope {
    val validFlightData = generateSequence {
        // 每次生成一个新的异步请求任务
        async {
            println("Started fetching Flight info.")
            client.get<String>(FLIGHT_ENDPOINT).also {
                println("Finished fetching Flight info.")
            }
        }
    }
    // 逐个等待异步任务结果,直到找到非Canceled的响应
    .map { it.await() }
    .first { !isCanceled(it) }

    // 后续处理有效的航班数据validFlightData
}

代码说明

  • generateSequence会惰性生成新的async任务,只有当前请求返回状态为Canceled时,才会生成下一个请求任务,避免不必要的提前执行。
  • map { it.await() }负责等待每个异步任务的结果,将Deferred<String>转换为实际的响应文本。
  • first { !isCanceled(it) }会遍历序列,直到找到第一个满足"状态非Canceled"的元素,终止序列生成。

如果需要避免过于频繁调用API,可以在async块内添加延迟,比如delay(1000)(单位:毫秒)来调整轮询间隔:

async {
    println("Started fetching Flight info.")
    delay(1000) // 每次请求前等待1秒
    client.get<String>(FLIGHT_ENDPOINT).also {
        println("Finished fetching Flight info.")
    }
}

内容的提问来源于stack exchange,提问作者arzhang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:50:37