在 Kotlin 中等待来自多个 callbacks/lambdas 的结果
Wait for result from multiple callbacks/lambdas in Kotlin
我正在用 Kotlin 开发一个应用程序。在此之前,我的网络电话不必一起使用。我现在处于需要进行两个并发网络调用的位置,暂停直到我收到他们的两个响应,然后继续执行。我正在尝试完成这样的事情:
//first networking call, get resourceOne
var resourceOne : String?
Server.asyncRequest(RequestBuilder(endpoints.second, ids, params)) { resource: String?, error: ServiceError? ->
resourceOne = resource
}
//second networking call, get resourceTwo
var resourceTwo : String?
Server.asyncRequest(RequestBuilder(endpoints.third, ids, params)) { resource: String?, error: ServiceError? ->
resourceTwo = resource
}
//do something here wiith resourceOne and resourceTwo
我的 asyncRequest 函数的函数头是:
fun asyncRequest(requestBuilder: RequestBuilder, completion: (resource: String?, error: ServiceError?) -> Unit) {
它只是包装了一个 okhttp 请求并做了一些额外的事情 processing/parsing。通常我只会获取结果(资源)并在完成 lambda 中处理它,但由于我需要这两个值,所以我不能在这里这样做。我试过做类似于 this 的事情,但是我的 asyncRequest 函数没有 return 类型,所以我无法像 link 那样做 async/await .
你可以用 Coroutines 和 Flow 一起做,像这样:
使用 suspendCancellableCoroutine {...}
块将 回调 转换为 可暂停函数:
suspend fun <T> request(requestBuilder: RequestBuilder): T = suspendCancellableCoroutine { cont ->
Server.asyncRequest(requestBuilder) { resource: T, error: ServiceError? ->
if(error != null)
cont.resumeWithException(error) // Makes the Flow throw an exception
else
cont.resume(resource) // Makes the Flow emit a correct result
}
}
创建一个 Flow 以发出 第一个请求:
val resourceOneFlow = flow {
emit(request<String>(RequestBuilder(endpoints.second, ids, params)))
}
创建一个 Flow 以发出 第二个请求:
val resourceTwoFlow = flow {
emit(request<String>(RequestBuilder(endpoints.third, ids, params)))
}
结合两个流与zip
运算符:
val requestsResultFlow = resourceOneFlow.zip(resourceTwoFlow) { resourceOne, resourceTwo ->
// Build whatever you need with resourceOne and resourceTwo here and let it flow
"$resourceOne $resourceTwo".length // Here I concatenate both strings and return its length
}
Activate/Start 使用 collect
运算符的 Flow 并使用其 result:
requestsResultFlow.collect { length ->
// Consume the result here
println("$length") // Here I print the number received
}
您有 Flow 文档 here。
我正在用 Kotlin 开发一个应用程序。在此之前,我的网络电话不必一起使用。我现在处于需要进行两个并发网络调用的位置,暂停直到我收到他们的两个响应,然后继续执行。我正在尝试完成这样的事情:
//first networking call, get resourceOne
var resourceOne : String?
Server.asyncRequest(RequestBuilder(endpoints.second, ids, params)) { resource: String?, error: ServiceError? ->
resourceOne = resource
}
//second networking call, get resourceTwo
var resourceTwo : String?
Server.asyncRequest(RequestBuilder(endpoints.third, ids, params)) { resource: String?, error: ServiceError? ->
resourceTwo = resource
}
//do something here wiith resourceOne and resourceTwo
我的 asyncRequest 函数的函数头是:
fun asyncRequest(requestBuilder: RequestBuilder, completion: (resource: String?, error: ServiceError?) -> Unit) {
它只是包装了一个 okhttp 请求并做了一些额外的事情 processing/parsing。通常我只会获取结果(资源)并在完成 lambda 中处理它,但由于我需要这两个值,所以我不能在这里这样做。我试过做类似于 this 的事情,但是我的 asyncRequest 函数没有 return 类型,所以我无法像 link 那样做 async/await .
你可以用 Coroutines 和 Flow 一起做,像这样:
使用 suspendCancellableCoroutine {...}
块将 回调 转换为 可暂停函数:
suspend fun <T> request(requestBuilder: RequestBuilder): T = suspendCancellableCoroutine { cont ->
Server.asyncRequest(requestBuilder) { resource: T, error: ServiceError? ->
if(error != null)
cont.resumeWithException(error) // Makes the Flow throw an exception
else
cont.resume(resource) // Makes the Flow emit a correct result
}
}
创建一个 Flow 以发出 第一个请求:
val resourceOneFlow = flow {
emit(request<String>(RequestBuilder(endpoints.second, ids, params)))
}
创建一个 Flow 以发出 第二个请求:
val resourceTwoFlow = flow {
emit(request<String>(RequestBuilder(endpoints.third, ids, params)))
}
结合两个流与zip
运算符:
val requestsResultFlow = resourceOneFlow.zip(resourceTwoFlow) { resourceOne, resourceTwo ->
// Build whatever you need with resourceOne and resourceTwo here and let it flow
"$resourceOne $resourceTwo".length // Here I concatenate both strings and return its length
}
Activate/Start 使用 collect
运算符的 Flow 并使用其 result:
requestsResultFlow.collect { length ->
// Consume the result here
println("$length") // Here I print the number received
}
您有 Flow 文档 here。