Skip to content

Instantly share code, notes, and snippets.

@gdotdesign
Last active March 19, 2020 21:38
Show Gist options
  • Save gdotdesign/bc0117e17b984c09097a643092a18aac to your computer and use it in GitHub Desktop.
Save gdotdesign/bc0117e17b984c09097a643092a18aac to your computer and use it in GitHub Desktop.
WebSocket in Mint
record Provider.WebSocket.Subscription {
onOpen : Function(WebSocket, Promise(Never, Void)),
onMessage : Function(String, Promise(Never, Void)),
onError : Function(Promise(Never, Void)),
onClose : Function(Promise(Never, Void)),
url : String
}
provider Provider.WebSocket : Provider.WebSocket.Subscription {
fun open (url : String, socket : WebSocket) : Array(a) {
for (subscription of subscriptions) {
subscription.onOpen(socket)
} when {
subscription.url == url
}
}
fun message (url : String, data : String) : Array(a) {
for (subscription of subscriptions) {
subscription.onMessage(data)
} when {
subscription.url == url
}
}
fun error (url : String) : Array(a) {
for (subscription of subscriptions) {
subscription.onError()
} when {
subscription.url == url
}
}
fun close (url : String) : Array(a) {
for (subscription of subscriptions) {
subscription.onClose()
} when {
subscription.url == url
}
}
fun update : Void {
`
(() => {
const connections = this._connections || (this._connections = new Map)
const subscriptions = this.subscriptions.values()
// create connections if not present
for (let item of subscriptions) {
if (!this._connections.has(item.url)) {
let socket = new WebSocket(item.url)
this._connections.set(item.url, socket)
socket._message = (event) => #{message(`item.url`, `event.data`)}
socket._error = () => #{error(`item.url`)}
socket._close = () => #{close(`item.url`)}
socket._open = () => #{open(`item.url`, `socket`)}
socket.addEventListener("message", socket._message)
socket.addEventListener("error", socket._error)
socket.addEventListener("close", socket._close)
socket.addEventListener("open", socket._open)
}
}
// drop connections that does not have subscriptions
for (let item of this._connections) {
const socket = item[1]
const url = item[0]
const subscriptionCount =
#{subscriptions}.filter((subscription) => {
return subscription.url === url
}).length
if (subscriptionCount == 0) {
socket.removeEventListener("message", socket._message)
socket.removeEventListener("error", socket._error)
socket.removeEventListener("close", socket._close)
socket.removeEventListener("open", socket._open)
socket.close()
}
}
})()
`
}
fun attach : Void {
update()
}
fun detach : Void {
update()
}
}
module WebSocket {
fun send (data : String, socket : WebSocket) : Promise(Never, Void) {
`#{socket}.send(#{data})`
}
}
component Main {
use Provider.WebSocket {
url = "wss://echo.websocket.org",
onMessage = handleMessage,
onError = handleError,
onClose = handleClose,
onOpen = handleOpen,
}
fun handleClose : Promise(Never, Void) {
sequence {
Debug.log("Closed...")
next { }
}
}
fun handleError : Promise(Never, Void) {
sequence {
Debug.log("Errored...")
next { }
}
}
fun handleOpen (socket : WebSocket) : Promise(Never, Void) {
sequence {
Debug.log("Opened...")
WebSocket.send("Some data", socket)
next { }
}
}
fun handleMessage (data : String) : Promise(Never, Void) {
sequence {
Debug.log("Message recieved: " + data)
next { }
}
}
fun render : Html {
<div>
<{ "Websocket provider" }>
</div>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment