I have recently started using socket-io for a live-chatting feature in a project of mine. I have everything working fine but as of now, I have all the server side socket-io stuff (connection, middleware, event handlers, etc.) in the main "index.js" file. It isn't a big deal now as I am only listening to a couple of events, but I would like to organize and separate the code into smaller files before it gets out of hand.
Here is an example of what the socket-io portion of the code looks like in my index.js file:
const express = require("express");
const app = express();
const http = require("http");
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
const jwt = require("jsonwebtoken");
const activeSockets = {};
io.use((socket, next) => {
const { token } = socket.handshake.auth;
if (!token) return next(new Error("Invalid or missing token"));
const { _id } = jwt.verify(token, process.env.JWT_KEY);
socket.handshake.auth._id = _id;
next();
});
const addSocket = (socket) => {
const { _id } = socket.handshake.auth;
if (!activeSockets[_id]) activeSockets[_id] = [socket.id];
else activeSockets[_id] = [...activeSockets[_id], socket.id];
};
const removeSocket = (socket) => {
const { _id } = socket.handshake.auth;
if (!_id || !activeSockets[_id]) return;
const index = activeSockets[_id].indexOf(socket.id);
activeSockets[_id].splice(index, 1);
if (activeSockets[_id].length < 1) delete activeSockets[_id];
};
io.on("connection", (socket) => {
addSocket(socket);
socket.on("typing", (isTyping, recipients, conversation, sender) => {
recipients.forEach((recipient) => {
if (activeSockets[recipient._id]) {
activeSockets[recipient._id].forEach((r) => {
socket.to(r).emit("typing", isTyping, conversation, sender);
});
}
});
});
socket.on("sendMessage", ({ message, recipients, conversation }) => {
recipients.forEach((recipient) => {
if (activeSockets[recipient._id]) {
activeSockets[recipient._id].forEach((r) => {
socket.to(r).emit("receiveMessage", { message, conversation });
});
}
});
});
socket.on("disconnect", () => {
removeSocket(socket);
});
});
const port = process.env.PORT || 5000;
server.listen(port, () => {
console.log("Listening: ", port);
});
I'm just struggling to find an efficient way to extract the socket-io code into smaller more organized pieces. Should the only thing in index.js related to socket-io be the connection itself? And then I have files for different event handlers that take an "io" parameter and then I call "io.on(...)" in those external functions? Or perhaps should I listen for all the events in index.js and then extract only the logic of each event into separate files? Something like:
io.on("eventName", someExternalFunction)
This is my first experience with socket-io so I'm not too sure of the "best practices".
Thank you to anyone who can offer help!