LExNEL
2/9/2018 - 4:46 PM

kotlin-websocket-example.kt

import org.w3c.dom.MessageEvent
import org.w3c.dom.WebSocket
import kotlin.browser.window
 
class KWebSocketImpl(val url : String, val reconnectDelayMillis: Int, val listener : (dynamic) -> Unit) {
    private var currentSocket : WebSocket? = null
    private val queue = arrayListOf<String>()
    private var closed = false
 
    init {
        connect()
    }
 
    fun stop() {
        closed = true
        try {
            currentSocket?.close()
        } catch (ignore : Throwable) {
            currentSocket = null
        }
    }
 
    fun send(o: Any) {
        if (closed) {
            throw IllegalStateException("Socket already stopped")
        }
 
        val text = JSON.stringify(o)
        queue.add(text)
 
        flush()
    }
 
    private fun flush() {
        val s = currentSocket ?: return
 
        try {
            val iterator = queue.iterator()
            while (iterator.hasNext()) {
                val text = iterator.next()
 
                s.send(text)
 
                iterator.remove()
            }
        } catch (ignore : Throwable) {
        }
    }
 
    private fun onMessage(message : dynamic) {
        listener(message)
    }
 
    private fun reconnectWithDelay() {
        window.setTimeout({
            connect()
        }, reconnectDelayMillis)
    }
 
    private fun connect() {
        try {
            tryConnect()
        } catch (any : Throwable) {
            reconnectWithMessageAndDelay()
        }
    }
 
    private fun reconnectWithMessageAndDelay() {
        console.error("WebSocket ($url) connection failure, will reconnect in ${reconnectDelayMillis / 1000.0}s")
        reconnectWithDelay()
    }
 
    private fun tryConnect() {
        val socket = WebSocket(url)
        fun closeSocket() {
            try {
                currentSocket?.close()
                socket.close()
            } finally {
                currentSocket = null
            }
        }
 
        socket.onopen = {
            if (currentSocket !== socket) {
                currentSocket?.close()
                currentSocket = socket
            }
 
            window.setTimeout({
                flush()
            }, 0)
        }
 
        socket.onerror = {
            closeSocket()
            reconnectWithMessageAndDelay()
        }
 
        socket.onmessage = {
            if (it is MessageEvent) {
                val data = it.data
                console.log("Received from websocket", data)
                if (data is String) {
                    onMessage(JSON.parse(data))
                }
 
                flush()
            }
        }
 
        socket.onclose = {
            if (socket === currentSocket) {
                currentSocket = null
            }
 
            if (!closed) {
                tryConnect()
            }
        }
    }
}