针对JavaScript时在Kotlin协同程序中使用runBlocking?

针对JavaScript时在Kotlin协同程序中使用runBlocking?,kotlin,kotlin-coroutines,kotlin-js,Kotlin,Kotlin Coroutines,Kotlin Js,有没有一种方法可以编写下面的Kotlin代码,以便它在JVM和JavaScript上以相同的方式编译和工作 fun <A: Any> request(request: Any): A = runBlocking { suspendCoroutine<A> { cont -> val subscriber = { response: A -> cont.resume(response) }

有没有一种方法可以编写下面的Kotlin代码,以便它在JVM和JavaScript上以相同的方式编译和工作

fun <A: Any> request(request: Any): A  = runBlocking {
    suspendCoroutine<A> { cont ->
        val subscriber = { response: A ->
                cont.resume(response)
        }
        sendAsync(request, subscriber)
    }
}


fun <Q : Any, A : Any> sendAsync(request: Q, handler: (A) -> Unit) {

    // request is sent to a remote service,
    // when the result is available it is passed to handler(... /* result */)

}
fun请求(请求:任意):A=runBlocking{
suspendCoroutine{cont->
val订户={响应:A->
续简历(回复)
}
sendAsync(请求、订户)
}
}
funsendasync(请求:Q,处理程序:(A)->Unit){
//请求被发送到远程服务,
//当结果可用时,它将传递给处理程序(…/*result*/)
}
当编译以JVM为目标时,代码可以编译并正常工作。
由于不存在函数runBlocking,以JavaScript为目标时会发出编译错误。您的主要问题是您没有要求实际需要的东西。您编写的代码启动一个协同程序,将其挂起,然后阻塞,直到完成。这完全等同于根本没有协同路由,只是发出阻塞网络请求,这是JavaScript不可能允许的

实际上,您需要做的是返回到
request()
的调用站点,并将其包装在
launch
中:

GlobalScope.launch(Dispatchers.Default) {
    val result: A = request(...)
    // work with the result
}
有了它,您可以将请求函数重写为

suspend fun <A: Any> request(request: Any): A = suspendCancellableCoroutine {
    sendAsync(request, it::resume)
}
suspend-fun请求(请求:Any):A=suspendcancelablecoroutine{
sendAsync(请求,it::resume)
}

我不认为GlobalScope::launch是Kotlin js协同程序库的一部分-如果目标是js,则不会编译此代码。我还试图避免在“请求”中添加“挂起”方法的签名,因为这意味着调用站点必须包装在一个coroutine
GlobalScope
中,它位于
kotlinx.coroutines.experimental
中,因此它必须在任何平台上可用,但我不知道它是否是JS上的最佳选项。您无法避免挂起和启动协同程序,因为这是其工作原理的本质。啊,一个重要的注意事项:我的代码是根据最近发布的kotlinx协同程序实验版的
0.26
编写的。它不推荐几种关键机制,如无接收器的全局
启动