代码之家  ›  专栏  ›  技术社区  ›  BillyDean

等待来自Kotlin中多个回调/lambda的结果

  •  0
  • BillyDean  · 技术社区  · 5 年前

    我在科特林做一个应用程序。直到现在,我的网络电话还不需要一起使用。现在我需要进行两个并发的网络调用,暂停直到我收到它们的两个响应,然后继续执行。我正努力完成这样的事情:

        //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请求,并进行一些额外的处理/解析。通常,我只需要获取结果(资源)并在完成lambda内处理它,但是由于我需要两个值,所以不能在这里这样做。我试过做类似的事情 this 但是我的asyncRequest函数没有返回类型,所以我无法像link那样执行async/await。

    0 回复  |  直到 5 年前
        1
  •  3
  •   Glenn Sandoval    5 年前

    你可以用它 协同程序 像这样:

    转弯 回拨 可悬函数 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
        }
    }
    

    创建 流量 使 :

    val resourceOneFlow = flow {
        emit(request<String>(RequestBuilder(endpoints.second, ids, params)))
    }
    

    创建 使 :

    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
    }
    

    流量 collect 运算符并使用其 结果

    requestsResultFlow.collect { length ->
        // Consume the result here
        println("$length") // Here I print the number received
    }
    

    你有 here .