Using runBlocking in Kotlin Coroutines when targeting JavaScript?

Viewed 1814

Is there a way to write the Kotlin code below so that it compiles and works the same way on the JVM and in 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 */)

}

The code compiles and works fine when compiled to target the JVM. A compilation error is emitted when targeting JavaScript due to non-existent function runBlocking

1 Answers

Your main problem is that you aren't asking for the thing you actually need. The code you wrote starts a coroutine, suspends it, then blocks until it's done. This is exactly equivalent to having no coroutines at all and just making a blocking network request, which is something you can't possibly expect JavaScript to allow you.

What you actually have to do is step back to the call site of request() and wrap it in a launch:

GlobalScope.launch(Dispatchers.Default) {
    val result: A = request(...)
    // work with the result
}

With this in place you can rewrite your request function to

suspend fun <A: Any> request(request: Any): A = suspendCancellableCoroutine {
    sendAsync(request, it::resume)
}
Related