Recommendations for using coroutines in Kotlin JS


#1

Hi all!

At my work been writing a SPA using Kotlin compiled to JS for some time now - since before v 1.0. To solve asynchronous XmlHttpRequest calls we have been using Bluebird Promise (bridged to Kotlin using external).

However we want to move away using an external library and rather use what Kotlin JS offers. So far we have been using the following “home made” launch routine, to launch the coroutines with:

fun launch(block: suspend () -> Unit, errorHandler: (Throwable) -> Unit) {
    block.startCoroutine(object : Continuation<Unit> {
        override val context: CoroutineContext get() = EmptyCoroutineContext
        override fun resume(value: Unit) {}
        override fun resumeWithException(exception: Throwable) {
            errorHandler.invoke(exception)
        }
    })
}

Usage:

launch(block = {

      // Call some suspending functions

   }, errorHandler = { error: Throwable ->

      // Handle error in an appropriate way
   }
)

This works like a charm!

But after I discovered this project: https://github.com/Kotlin/kotlinx.coroutines
I’ve been wondering if I should replace my launch-routine with the launch routine from this project?

Also I’m looking for features like:

  • Possibility to lazily start the co-routine
  • Have an object returned representing the co-routine for lazily execution at some later time.

Is this when I should use async with start = CoroutineStart.LAZY and keep the returned Job object for execution later?


#2

Indeed, you can lazily launch coroutines with kotlinx-coroutines-core-js. It has two ways to start a coroutine: launch (returns a Job) is for coroutines that are not expected to return a result, but simply represent some background activity, while async (return a Deferred) is for coroutines that you plan to retrieve result later. You kind find about the difference here: https://stackoverflow.com/questions/46226518/what-is-the-difference-between-launch-join-and-async-await-in-kotlin-coroutines

Both accept an optional start = CoroutineStart.LAZY parameter. In case of a launch the coroutine is actually started when you invoke Job.start(), while with Deferred, in addition to that, it is started on a first Deferred.await() invocation.

Additional features that you might find useful include cancellation of coroutines and integration with JS Promise.