如何用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
相关产品推荐
相关产品推荐

