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}" }
}
}
}
}
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