Async await on the client (JavaScript)


#1

Is it possible to make use of Kotlins’s async await functionality on the client-side for making ajax calls?


#2

I don’t tested coroutine on Javascript but it should work.

Look at https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md#wrapping-callbacks

I’m writing something on it (using Vert.x)

Here some example code: https://github.com/fvasco/vertKtDemo/blob/master/src/main/kotlin/Verticle3.kt


#3

Yes. Kotlin JS provides the same low-level APIs for coroutines as Kotlin JVM. So, most of the examples given in the coroutines design document can be converted to JS almost as-is. There are also plans to port kotlinx.coroutines support library to JS with all the rich primitives it has, like launch/Job, async/Deferred, produce/actor/Channel, etc. You can track issue #33 on github.

Meanwhile, for your Promise integration needs it is extremely straightforward to define a suspending function that awaits for a completion of the JS Promise:

import kotlin.js.*

suspend fun <T> Promise<T>.await(): T = suspendCoroutine { cont -> 
    then({ cont.resume(it) }, { cont.resumeWithException(it) })                                                      
}

You can easily coroutinefy any other callback-based API as explained in the “Wrapping callbacks” section of the design document.

Now, suspending functions have to be called from a coroutine. You need to define some simple coroutine builder. Here is a simplified version of launch to “fire and forget” a coroutine (unlike its cousin from kotlinx.coroutines it does not return a Job):

import kotlin.coroutines.experimental.*

fun launch(block: suspend () -> Unit) {
    block.startCoroutine(object : Continuation<Unit> {
        override val context: CoroutineContext get() = EmptyCoroutineContext
        override fun resume(value: Unit) {}
        override fun resumeWithException(e: Throwable) { console.log("Coroutine failed: $e") }
    })
}

Combining both of them, you’ll be able to write callback-free code, like this:

launch {
    console.log("Yoo-Hoo! I'm in a coroutine now!")
    val result = doSomethingAsync().await() 
    console.log("I have a $result without callbacks!")
}

The advantages of that callback-free style really show up when you start doing complex logic, loops, etc. There are some better examples in the “Use cases” section of the design document.

You can also define a promise builder that would represent a future result of a coroutine as a JS Promise. The “Building futures” section of the design document explains the corresponding steps. It takes no more than a dozen lines of code.


#4

Hi elizarov,

Can you elaborate on that particular example ? That code compiles but throws an exception about suspendCoroutine missing.

Coroutine failed: TypeError: Kotlin.kotlin.coroutines.experimental.suspendCoroutine$f is not a function

(kotlin 1.1.51)


#5

Hi.

Sorry guys, it works fine. I was using an older version of kotlin