如何在Kotlin/JS的React按钮onClick事件中调用suspend函数?
在React-Kotlin中用suspend函数实现按钮点击获取数据
你当前代码里直接调用suspend fun fetchCat()编译失败,核心原因是挂起函数只能在协程上下文或另一个挂起函数中执行,而按钮的onClick回调是普通非挂起函数,无法直接触发挂起调用。要解决这个问题,需要借助React-Kotlin的协程工具创建合法的协程上下文。
实现步骤
- 确保项目引入
kotlinx-coroutines-react依赖(提供React组件的协程支持) - 使用
useCoroutineScope钩子获取与组件生命周期绑定的协程作用域,组件卸载时该作用域会自动取消所有子协程,避免内存泄漏 - 在
onClick回调中,通过协程作用域的launch方法启动协程,在协程内部调用挂起函数
完整修改后的代码
import kotlinx.browser.window import react.FC import react.Props import react.dom.html.ReactHTML.button import react.dom.html.ReactHTML.div import react.useState import kotlinx.coroutines.launch import react.useCoroutineScope import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine val MyComponent = FC<Props> { var text by useState("Click Load") // 获取绑定组件生命周期的协程作用域 val scope = useCoroutineScope() div { +text } button { +"Load" onClick = { text = "Loading..." // 启动协程执行挂起函数 scope.launch { try { val catFact = fetchCat() text = catFact } catch (e: Exception) { text = "加载失败: ${e.message}" } } } } } suspend fun fetchCat() = suspendCoroutine<String> { continuation -> window.fetch("https://catfact.ninja/fact") .then { response -> response.text() .then { text -> continuation.resume(text) } .catch { continuation.resumeWithException(it) } } .catch { continuation.resumeWithException(it) } }
简化挂起函数的写法
Kotlin/JS的协程库已经内置了对Promise的扩展函数await(),可以不用手动编写suspendCoroutine,直接将Promise转换为挂起调用,fetchCat可以简化为:
import kotlinx.coroutines.await suspend fun fetchCat(): String { val response = window.fetch("https://catfact.ninja/fact").await() return response.text().await() }
关键说明
useCoroutineScope:生成与组件生命周期绑定的协程作用域,组件卸载时自动取消所有子协程,防止异步任务在组件销毁后继续执行导致内存泄漏scope.launch:启动新协程,该协程运行在组件作用域内,允许调用挂起函数try-catch:捕获挂起函数可能抛出的异常,避免协程崩溃影响组件正常运行
内容的提问来源于stack exchange,提问作者Jordi
相关产品推荐
相关产品推荐

