Skip to content

Instantly share code, notes, and snippets.

@cy6erGn0m
Last active June 20, 2023 15:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cy6erGn0m/ed47b66ce50c6514f2bd to your computer and use it in GitHub Desktop.
Save cy6erGn0m/ed47b66ce50c6514f2bd to your computer and use it in GitHub Desktop.
This example demonstrates how to use WebSocket including reconnect when needed and error handling
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()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment