Websockets
WebSockets are a technology that provides full-duplex, persistent communication channels between a web server and a web client (typically a web browser).
Unlike HTTP, which is request-response based, WebSockets allow for continuous, bi-directional data exchange. This makes them ideal for applications that require real-time updates, such as online chat, collaborative editing, and real-time data visualization.
A Chat Application
Deno have websocket server builtin. Let's use Deno to write a simple chat application.
Add a server.js:
const clients = []
Deno.serve({
port: 3000,
handler: async (request) => {
if (request.headers.get("upgrade") == "websocket") {
const { socket, response } = Deno.upgradeWebSocket(request)
socket.onmessage = event => {
clients.forEach(x => {
if (x != socket) {
x.send(event.data)
}
})
}
socket.onclose = () => clients.splice(clients.indexOf(socket), 1)
socket.onerror = error => console.error("ERROR:", error)
socket.onopen = () => clients.push(socket)
return response
}
const file = await Deno.open("./index.html", { read: true })
return new Response(file.readable)
},
})
Add a index.html:
<!doctype html>
<style>
#container {
width: 400px;
padding: 50px;
display: flex;
gap: 20px;
flex-direction: column;
}
#output {
height: 300px;
border: 1px solid #ccc;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 5px;
padding: 5px;
}
.text {
background: green;
color: white;
border-radius: 5px;
padding: 5px;
}
.self {align-self: flex-end;}
.error {background: red;}
</style>
<div id="container">
<div id="output"></div>
<textarea id="input" rows=3></textarea>
</div>
<script>
const ws = new WebSocket("ws://127.0.0.1:3000")
const input = document.querySelector("#input")
function appendMessage(msg, type) {
const template = document.createElement("template")
template.innerHTML = `<div class="text ${type}">${msg}</div>`
document.querySelector("#output").appendChild(template.content.cloneNode(true))
}
input.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
event.preventDefault()
ws.send(input.value)
appendMessage(input.value, 'self')
input.value = ""
}
})
ws.onmessage = (e) => appendMessage(e.data, 'incoming')
ws.onerror = (e) => appendMessage(e.data, 'error')
</script>
Start the server, and open two browser tabs to chat.
deno run --allow-net=0.0.0.0:3000 --allow-read=index.html server.js