4

I am using KotlinX.html to emit HTML to an output stream (e.g. FileWriter in the next sample) and the resulting HTML view depends of asynchronous data from a CompletableFuture (e.g. cfArtist).

I want to immediately start emitting static HTML (i.e. <html><body><h1>Artist Info</h1>), then suspend until data is available and then proceed.

HTML builders of KotlinX.html API are inline functions with crossinline functions as parameter, thus I am not allowed to call await in corresponding lambdas (e.g. cfArtist.await()).

I do not want to await before start emitting HTML and do not want to create other coroutines either. Is there any way to await inside those crossinline lambdas?

suspend fun viewArtistInfo(fileName: String, cfArtist: CompletableFuture<Artist>) {
    // val artist = cfArtist.await() // Ok
    FileWriter(fileName).use {
        // val artist = cfArtist.await() // Ok
        it
            .appendHTML()
            .html {
                body {
                    h1 { +"Artist Info" }
                    val artist = cfArtist.await() // ERROR Suspension functions can be called only within coroutine body
                    p { +"From: ${artist.from}" }
                }
        }
    }
}
Miguel Gamboa
  • 8,855
  • 7
  • 47
  • 94
  • Why don’t you await and assign to a local variable before you enter the html DSL? How would this be effectively different from what you’re asking to be able to do? – Tenfour04 Sep 20 '22 at 16:09
  • Instead of start emitting `

    Artist Info

    ` consider that I am emitting a lot of useful information in a header. If I await and assign to a local variable before entering the html DSL then I will not send that useful header and the client will have to wait for `CompletableFuture` completion to see something.
    – Miguel Gamboa Sep 20 '22 at 16:18
  • So shouldn't you append some static html, then await your data, then append some more static html with another DSL chain? I don't use kotlinx.html, but this seems like how you would use the [streaming](https://github.com/kotlin/kotlinx.html/wiki/Streaming) functionality. – Tenfour04 Sep 20 '22 at 16:35
  • Not possible due to _function nesting_ approach. Note `p { }` call is nested in `body { }`. To follow your proposal the `body` tag would be closed before starting the `p` tag. – Miguel Gamboa Sep 20 '22 at 16:38
  • 1
    I imagine either the library provides a way to insert elements into already-written elements or it doesn’t. From my very quick look over their documentation, it doesn’t look to me like that’s supported but I could definitely be wrong. – Tenfour04 Sep 20 '22 at 16:53
  • 1
    I think that @Tenfour04 is right. What you ask is just not supported by the library. For me, it looks like authors of the library have not considered the use of suspendable functions in the dsl. There's also [an open issue](https://github.com/Kotlin/kotlinx.html/issues/189) that looks very similar to your use-case. – amanin Sep 30 '22 at 08:24

0 Answers0