3

我是 KMM 和协程的新手。有没有一种方法可以等待异步函数的响应,而无需使依赖函数也挂起?

代码示例

// In HttpClient.kt in commonMain

class MyHttpClient {
    val client = HttpClient()

    suspend fun get(url: String): String {
        client.get<String>(url)
    }
}

// In Another class in commonMain
class Foo {
    private val httpClient = MyHttpClient()

    fun performAction() { <--- #1
        val data = httpClient.get("server url")
        // So stuff with that data after its retrieve from server.
    }
}

// In iOS swift code
struct Example: View {

    var body: some View {
        Button {
            foo.performAction() <--- #2
        } label: {
            Text("Click Me")
        }
    }

}

如果我将 #1​​ 设为挂起函数 #2 需要不必要的回调。例子

// In iOS swift code
struct Example: View {

    var body: some View {
        Button {
            foo.performAction(completionHandler: handler)
        } label: {
            Text("Click Me")
        }
    }

    private func handler(response: KotlinUnit?, error: Error?) {
        // DO NOTHING
    }
}

我的单元测试也失败了,因为你不能让测试暂停功能并且runBlocking不在 commonMain 中。

4

1 回答 1

0

您不需要添加该完成回调。您所要做的就是从点击处理程序启动一个协程,如下所示:

    Button {
        viewScope.launch {
            foo.performAction()
            // add GUI code here that runs when action is done
        }
    } label: {
        Text("Click Me")
    }

如果您当前没有定义协程范围,您应该像这样(大约)添加它:

struct Example: View {
    private val viewScope = CoroutineScope(Dispatchers.Main)

    // adapt this to the actual way you get the "view closed" event
    fun onClose() { 
        viewScope.cancel()
    ​}

   ​...
}

Dispatchers.Main使您的协程在 GUI 线程上运行。由于您使用的是可挂起的 IO(正如您所见证的那样suspend fun get(url: String): String),因此无需使用任何其他线程。

于 2021-05-14T07:56:59.603 回答