基本上,我必须同时使用OkHttp
各种地址来发出网络请求。我只关心第一个成功的结果。我可以用Flow
on做Kotlin
吗?
我一直在环顾四周,但我一直在努力使请求并行运行,始终按顺序运行。
该代码基本上采用地址列表,并且应返回唯一有效的地址;如果无效,则返回null。
谢谢。
编辑:我应该提一下我打算在Android上使用它。我可能可以用RX做到这一点,但想学习Flow
。还试图限制我添加到应用程序中的库。
编辑:我已经将答案标记为正确,但是那不是我的做法,但是它使我非常接近我的做法,但是由于我是新手,Flow
所以我不知道我的做法是否正确,尽管我我确信在我测试之后它可以正常工作。
我有一个NoSuchElementException
找不到时抛出的函数。它调用searchForIPAsync
哪个suspend
函数完成所有OkHttp
工作并返回true|false
。
@Throws(NoSuchElementException::class)
private suspend fun findWorkingIP(ipsToTest: MutableList<String>): String? = ipsToTest
.asFlow()
.flatMapMerge(ipsToTest.size)
{ impl ->
flow<String?> {
val res = connectionHelper.searchForIPAsync(getURLToTest(impl))
if (res) {
emit(impl)
} else {
}
}
}.first()
然后调用此方法,并在未找到任何内容的情况下捕获异常:
try {
val ipFound = findWorkingIP(ipsToTest)
Log.w(TAG, "find: Got something " + ipFound);
return ipFound
} catch (ex: NoSuchElementException) {
Log.w(TAG, "find: not found");
}
尽管另一个答案中基于Flow的解决方案非常符合您的需求,但是不幸的是,从Kotlin 1.3.2开始,Flow的实现存在一个破坏它的错误。该错误已经有建议的修复程序,因此应该在下一个Kotlin修补程序版本中解决。同时,这是使用async
和Channel
代替的类似解决方案:
suspend fun getShortUrl(urls: List<String>): String = coroutineScope {
val chan = Channel<String?>()
urls.forEach { url ->
launch {
try {
fetchUrl(url)
} catch (e: Exception) {
null
}.also { chan.send(it) }
}
}
try {
(1..urls.size).forEach { _ ->
chan.receive()?.also { return@coroutineScope it }
}
throw Exception("All services failed")
} finally {
coroutineContext[Job]!!.cancelChildren()
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句