Kotlin/JS suspension function in an HTMLButtonElement EventListener

769 views Asked by At

I am writing a program targeting KotlinJS for the browser. I do not know much about Kotlinx's coroutines, but I need them to avoid freezing the thread for 20 minutes.

suspend fun getBigList(ids: bundleID) {
    val resp = GlobalScope.async{requestS("URLwithPARAMS${ids}")}
    val bigList = resp.await()?.let { it1 -> Json{ignoreUnknownKeys = true}.decodeFromString<LogList>(it1) }
    //do something with bigList, or return it and do something in the event listener, either way it will have to be a suspended function that makes HTTP requests based on the bigList
}
//requestS is a synchronous xmlHTTP request. wrapping synchronous with async instead of creating an async xmlHTTP request so that I can await on the response instead of using callbacks.

suspend fun main() {
    val button = document.getElementById("mybutton") as HTMLButtonElement
    val input = document.getElementById("myinput") as HTMLInputElement
    button.addEventListener("click", {
        val playerIDs = {/* data class instance derived from input.value */}
        getBigList(playerIDs)
    })
}

Calling getBigList in button.addEventListener causes an error, Suspension functions can be called only within coroutine body I understand why it does this (addEventListener is not suspendable), but I don't know how to get around it (I can't just tag button.addEventListener as 'suspend')

The final flow needs to be: User clicks button -> Program sends http request to external site, which returns a large (1000-4000) list of lets say for simplicity, random numbers. -> Program then takes those returned numbers and sends 1 new http request for each number (I will have to figure out how to ratelimit it).

I only include this extra information so that you may have all the information you need to tell me what I need to do for the event listener, and if I'm even using the right async idioms.

1

There are 1 answers

0
Anton Bannykh On BEST ANSWER

Seems like you want the button to trigger some asynchronous activity. One way to do that would be:

    button.addEventListener("click", {
        GlobalScope.launch {
            // This is a suspend lambda.
            // i.e. you can call getBigList here
            // The execution will suspend when needed and run until completion
        }
    })

Here launch is a function from the kotlinx.coroutines library.

This is similar to invoking an async function in JS.