Callbacks Vs JavaScript promises & Kotlin coroutines

Convert callback based asynchronous methods for more linear code, with Promises + Async/Await in JavaScript and Coroutines in Kotlin.

In JavaScript, wrap the callback based method inside a new Promise((resolve, reject) => {...}) call. Then call the resolve/reject method of the promise on callback completion. The result is an asynchronous promise that resolves with the result of the callback.

In Kotlin, wrap the callback based method inside a suspendCoroutine {continuation-> ...}. Then call continuation.resume or continuation.resumeWithException on callback completion. The result is an asynchronous/suspending Coroutine that returns the value of the callback.

A small drawback of these approaches is that they return a single value, while the callback can have multiple values. The solution to this is to wrap the values returned from the callback in an object (JS) or data class (Kotlin).

TIL: Webview @JavascriptInterface methods run in a different thread

I was trying to update a LiveData in a ViewModel from a Javascript method within the Webview. The Kotlin method was being called but the LiveData was not being updated. There were no errors either.

This fails silently:

@JavascriptInterface
fun onSelection(selection: String) {
    readerViewModel.setSelectedText(text)
}

After a lot of frustrating tinkering, I got the LiveData to update when I wrapped the update statement within a CoroutineScope.launch  on the Main thread.

This works:

@JavascriptInterface
fun onSelection(selection: String) {
    setSelectedText(selection)
}
...
private fun setSelectedText(text: String) {
    CoroutineScope(Dispatchers.Main).launch {
        readerViewModel.setSelectedText(text)
    }
}

It appears that the @JavascriptInterface methods are executed on a separate non-Main thread. Usually an exception is thrown when a ViewModel is updated from a non-Main thread in Kotlin. Surprisingly (and very confusingly), this exception isn’t thrown when updating the ViewModel from @JavascriptInterface. It just fails silently :/

Javascript class methods

My understanding of javascript object methods (pre-ES6) from Douglas Crockford’s post.

Public

Can’t access private members of the object

Anything created with this.xyz inside the constructor, or

Any methods added by MyObject.prototype.myMethod outside the constructor.

Private

Not accessible from outside the object definition (e.g. as myObj.myMethod())

Any variables or functions created inside the constructor with var or function abc(){...}.

Privileged

(I.e. publicly accessible, but can access private members)1

Methods declared with this.myMethod = function()... inside the constructor.

Continue reading