Requirements
I have the following user requirements:
- Document A can be edited in real-time by
n users - User A can edit the
document Aand everyone connected todocument Ashould see changes in real time - The same goes for
documents B, C, D, ..., n
I'm currently using socket.io in an express server to handle the real-time communication. The logic (reduced to a minimal reproducible example) is as follow:
- As soon as user opens
document A, he joins a room by emitting an eventjoin:roomto the websocket server - websocket server attaches the user to room
document A user Awrites something ondocument A,user Bwill receive the updates in real-timeuser Bleavesdocument A, he emits an eventleave:roomto websocket server
Minimum reproducible example
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, {
cors: {
origin: "*"
}
});
io.on('connection', (socket) => {
socket.on('join:room', (data) => {
console.log(`Joined room: ${data.roomId}`);
socket.join(data.roomId);
});
socket.on('text:insert', (data) => {
console.log(`Text inserted: ${data.roomId}`);
socket.to(data.roomId).emit('text:inserted', data);
});
socket.on('leave:room' , (data) => {
console.log('left room: ' + data.roomId);
socket.leave(data.roomId);
});
})
The code on the client is as follow (reproduced to a minimal reproducible example):
// main.js
import { io } from "socket.io-client";
window.io = io;
console.log('opened connection');
window.monacoSocket = io(process.env.MIX_WEBSOCKET_SERVER_URL);
// custom.js
function onTextInserted({ user, event }) {
console.log('Text have been inserted: ' + event);
}
document.querySelectorAll('.files')
.forEach((item) => {
item.dblclick(() => {
window.monacoSocket.removeAllListeners();
window.monacoSocket.on('text:inserted', ({ event, user }) => onTextInserted({ user, event }));
});
});
This codes works great when we are working in the same document
The problem
The problem starts when I move from document A to document B. Whenever I open my page and visit only document A, I can see that only a single websocket connection was opened and everything works as expected (from both user A and user B perspective):
Now, if I follow the following steps:
- as
user AI opendocument A - as
user BI opendocument A - as
user AI make a change indocument A - as
user AI switch todocument B - as
user AI make changes todocument B - as
user BI see a new connection opening in mynetwork tab
As soon as this new connection is opened, user A and user B will not be receiving changes anymore
Questions
I have a couple of questions to help me understand what exactly is going on here.
When I add new listeners to a
socket.io-clientinstance, should thesocket.iolibrary open a new connection as it is doing right now?What exactly is causing the new connection to be opened? Is it safe to assume that if no new connection would be open, the code should work as intended - the
console.loginonTextInsertedfunction should print?On my anonymous function on
dbclick, should I see remove all listeners?
I highly appreciate anyone taking the time to answer these questions.

