Last active
July 16, 2024 02:48
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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