针对JavaScript时在Kotlin协同程序中使用runBlocking?
有没有一种方法可以编写下面的Kotlin代码,以便它在JVM和JavaScript上以相同的方式编译和工作针对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) }
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,则不会编译此代码。我还试图避免在“请求”中添加“挂起”方法的签名,因为这意味着调用站点必须包装在一个coroutineGlobalScope
中,它位于kotlinx.coroutines.experimental
中,因此它必须在任何平台上可用,但我不知道它是否是JS上的最佳选项。您无法避免挂起和启动协同程序,因为这是其工作原理的本质。啊,一个重要的注意事项:我的代码是根据最近发布的kotlinx协同程序实验版的0.26
编写的。它不推荐几种关键机制,如无接收器的全局启动
。