5

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 Answer 1

4

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)
}
Sign up to request clarification or add additional context in comments.

4 Comments

I don't think GlobalScope::launch is part of the Kotlin js coroutine library - this code won't compile if the target is JS
Also, I'm trying to avoid adding "suspend" to the "request" method's signature because that mean the call site has to be wrapped in a coroutine
GlobalScope is in kotlinx.coroutines.experimental so it must be available on any platform, however I don't know if it's the best option on JS. You can't avoid suspend and launching coroutines because that's the essence of how this works.
Ah, one important note: my code is written against version 0.26 of kotlinx-coroutines-experimental, recently released. It deprecates several key mechanisms like the global launch without a receiver.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.