Implement a real-time chat with WebSocket
You can use the ws
handler to upgrade a GET
route to WebSocket
. To use
this to implement a real-time chat application, first create a HTML client.
This assumes you have installed and loaded
@primate/html
in your config file.The HTML frontend will automatically extract <style>
and <script>
tags and
bundle them into the rest of your application.
HTMLcomponents/index.html
<script>
window.addEventListener("load", () => {
const ws = new WebSocket(new URL("/ws?limit=20", window.location.href));
ws.addEventListener("open", () => {
document.querySelector("#chat").addEventListener("keypress", event => {
if (event.key === "Enter") {
ws.send(event.target.value);
event.target.value = "";
}
})
});
ws.addEventListener("message", message => {
const chatbox = document.querySelector("#box");
const div = document.createElement("div");
div.innerText = message.data;
chatbox.appendChild(div);
})
});
</script>
<style>
#box {
background-color: lightgrey;
width: 300px;
height: 300px;
overflow: auto;
}
</style>
<div id="box"></div>
<input id="chat" placeholder="Type to chat" />
Serve the client from the index route (/
).
TypeScriptroutes/index.ts
import response from "primate/response";
import route from "primate/route";
route.get(() => response.view("index.html"));
At the /ws
route, upgrade with the ws
handler, maintaining a list of active
web socket connections and distributing messages to all active chat
participants.
TypeScriptroutes/ws.ts
import uint from "pema/uint";
import response from "primate/response";
import route from "primate/route";
const sockets = new Set<any>();
route.get(request => {
// limit the number of messages a client can send
const limit = uint.coerce.default(20).parse(request.query.get("limit"));
let n = 1;
return response.ws({
close(socket) {
sockets.delete(socket);
},
message(_, message) {
[...sockets.values()].forEach(socket => {
if (n > 0 && n < limit) {
n++;
socket.send(message);
}
});
},
open(socket) {
sockets.add(socket);
},
});
});