Home > Software design >  Using async func in Compose Web
Using async func in Compose Web

Time:01-04

I should use Ktor client in Compose Web. But, It can't be called in Compose Web due to async/non-async problem. Environment is template project made by IntelliJ IDEA.

First, I use this:

val client=HttpClient(Js){
    install(ContentNegotiation){
        json()
    }
}


suspend fun shorterCall(url:String):String{
    val response = client.get(SERVER_NAME) {
        contentType(ContentType.Application.Json)
        parameter("url", url)
    }
    return response.bodyAsText()
}

suspend fun main() {
    var i by mutableStateOf("")

    renderComposable(rootElementId = "root") {
        Div({ style {
            height(100.vh)
            margin(0.px)
            width(100.vw)
        } }) {
            Input(type = InputType.Url) {
                onInput {
                    val input=it.value.trim()
                    if(input.startsWith("http"))
                        i=shorterCall(input)
                    else
                        i="NaN"
                }
            }
            Text(i)
        }
    }
}

Then, I got that error:

Suspend function can be called only within a coroutine body.

So, I tried another one:

import kotlinx.coroutines.*

fun shorterCall(url:String):String{
    var ret:String
    suspend fun t():String {
        val response = client.get(SERVER_NAME) {
            contentType(ContentType.Application.Json)
            parameter("url", url)
        }
        return response.bodyAsText()
    }
    runBlocking{
        ret=t()
    }
    return ret
}


//main func is same as upper one.

Then, I got that error:

Unresolved reference: runBlocking

editing body 1: When I use GlobalScope.launch or js("JSCode"), It raise that error:

e: Could not find "kotlin" in [/home/user/.local/share/kotlin/daemon]
e: java.lang.IllegalStateException: FATAL ERROR: Could not find "kotlin" in [/home/user/.local/share/kotlin/daemon]

(a lot of internal errors bellow)

CodePudding user response:

You can use the GlobalScope.launch() method to launch a job for a request in a browser environment:

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import io.ktor.client.*
import io.ktor.client.engine.js.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.renderComposable

fun main() {
    val client = HttpClient(Js) {}
    var i by mutableStateOf("")

    renderComposable(rootElementId = "root") {
        Div({
            style {
                height(100.vh)
                margin(0.px)
                width(100.vw)
            }
        }) {
            Input(type = InputType.Url) {
                onInput {
                    val input = it.value.trim()

                    if (input.startsWith("http")) {
                        GlobalScope.launch {
                            i = client.shorterCall(input)
                        }
                    } else {
                        i = "NaN"
                    }
                }
            }
            Text(i)
        }
    }
}

suspend fun HttpClient.shorterCall(url: String): String {
    val response = get(url) {
        contentType(ContentType.Application.Json)
    }
    return response.bodyAsText()
}
  • Related