kwebio / kweb-core

A Kotlin web framework
https://docs.kweb.io/book
GNU Lesser General Public License v3.0
969 stars 57 forks source link

elementScope only ends, after JavaScript Call #617

Open chucky2002 opened 5 months ago

chucky2002 commented 5 months ago

How does the function elementScope() work and when does it end? According to my understanding, the coroutines from elementScope() run as long as the associated page is active. When the page is closed, the ElementScope also ends, along with the coroutines contained within it. Is this correct?

My tests have shown that this doesn't work as such. Below is an example of a simple implementation. When the page is opened, a label that is continuously updated by a coroutine in ElementScope is displayed. If I refresh the page in the browser, a second coroutine starts, and the original one continues to run. I would have expected that the original coroutine would end when the page is closed.

I have found out that the coroutine is ended when the function browser.callJsFunctionWithResult("") is called within it. My goal is to have a coroutine on the page run as long as the element to be updated exists. It should carry out a kind of polling on an external resource. If the element no longer exists, the coroutine should be ended. How can I implement this?


import kotlinx.coroutines.*
import kweb.Kweb
import kweb.label
import java.awt.Desktop
import java.net.URI
import java.util.concurrent.atomic.AtomicInteger

class WebserverCoroutineTest {

    val coroutineId = AtomicInteger(0)

    @org.junit.Test
    fun test1() {
        runBlocking {
            Kweb(port = 16097, debug = true) {
                doc.body {
                    /* get ID of the thread */
                    val id = coroutineId.incrementAndGet()

                    /* Add Label to Page */
                    val labelText = kvar("")
                    label().text(labelText)

                    /* Update the label every 100ms and print Coroutine Id */
                    elementScope().launch {
                        while (isActive) {
                            // if this is called, the Coroutine quits, if the WS session is disconnected
                            browser.callJsFunctionWithResult("")

                            val newText = "Coroutine $id: ${System.currentTimeMillis()}"
                            println(newText)
                            labelText.value = newText
                            delay(100)
                        }
                    }
                }
            }

            Desktop.getDesktop().browse(URI("http://localhost:16097"))

            // wait for 10 minutes
            delay(1000*60*10)
        }
    }
}