socket.io
socket.io copied to clipboard
Events before disconnection dropped
Describe the bug
In a Socket.IO application, events emitted just before a client disconnects are not properly handled by specific on(...) listeners. While the onAny(...) listener detects these events, the specific on(...) listeners do not. This issue occurs with any event emitted just before disconnection. The reason onAny(...) works is that it runs before the dispatch, which relies on process.nextTick.
To Reproduce
Socket.IO server version: 4.x.x (replace with your version)
Server
import { Server } from "socket.io";
const io = new Server(3000, {});
io.on("connection", (socket) => {
console.log(`connect ${socket.id}`);
// Example event listener (applies to any event)
socket.on("exampleEvent", () => {
console.log(`exampleEvent received before disconnect ${socket.id}`);
});
// Using onAny listener
socket.onAny((event, ...args) => {
console.log(`onAny received ${event} before disconnect ${socket.id}`);
});
socket.on("disconnect", () => {
console.log(`disconnect ${socket.id}`);
});
});
Socket.IO client version: 4.x.x (replace with your version)
Client
import { io } from "socket.io-client";
const socket = io("ws://localhost:3000/", {});
socket.on("connect", () => {
console.log(`connect ${socket.id}`);
// Emit any event just before disconnecting
socket.emit("exampleEvent");
socket.disconnect();
});
socket.on("disconnect", () => {
console.log("disconnect");
});
Expected behavior
The on listener for any event (e.g., exampleEvent) should detect and handle the event before disconnection. Currently, the onAny listener detects the event, but the specific on(...) listener does not. This occurs because onAny runs before the dispatch, which relies on process.nextTick, allowing it to detect the event before disconnection, see https://github.com/socketio/socket.io/blob/175a2c58c1bc37eb9b87f87df47e1f9388b01d55/packages/socket.io/lib/socket.ts#L559-L575.
Platform:
Not relevant
Additional context
This issue affects any event emitted just before disconnection. The onAny listener works because it operates before the event dispatch process, which uses process.nextTick. As a result, events are detected by onAny but missed by the specific on(...) listeners, which rely on the dispatch mechanism that happens after disconnection begins.