如何使用Kotlin和函数式编程进行迭代直到满足条件?

8fq7wneg  于 2023-02-09  发布在  Kotlin
关注(0)|答案(1)|浏览(143)

我使用的API返回如下文本:BW3511,HGP,ITP,Canceled,32 .我必须继续获取,直到我得到一个不是“已取消”的响应。
此代码获取数据:

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>
检查是否已取消:

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

如何使用函数式编程风格重复client.get<String>(FLIGHT_ENDPOINT)直到满足条件?
我尝试使用takeIf,但是我必须至少得到一个结果,并且它不能是可空类型。

mqkwyuun

mqkwyuun1#

正如@Jorn的评论所说,这看起来像是函数式风格的过度使用,它可以通过一个简单的循环来实现,这样读者可能会更清楚:

fun getNextNotCancelled() {
    while (true) {
        val response = client.get<String>(FLIGHT_ENDPOINT)
        if (!isCanceled(response)) return response
    }
}

如果你的实际情况更复杂,所以你有几个过滤器,等等,或者出于任何其他原因你真的需要声明性地做这件事,那么你需要创建某种无限生成器。对于经典的同步代码来说,这意味着序列,而对于异步代码来说,这意味着流。
使用序列的示例:

generateSequence { client.get<String>(FLIGHT_ENDPOINT) }
    .first { !isCanceled(it) }

流量:

flow {
    while (true) {
        emit(client.get<String>(FLIGHT_ENDPOINT))
    }
}.first { !isCanceled(it) }

正如你所说的,你使用协程,我假设你会选择后者。正如你所看到的,它与我们最初的基于循环的方法非常相似,只是更复杂。当然,我们可以创建一个类似的generateFlow()实用函数,然后它会更短。

相关问题