You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 14:27:23