Comprehensive event system for monitoring connection lifecycle, data transmission, and error handling across all transport types with EventEmitter-based architecture.
Complete event system for monitoring socket connection lifecycle and data flow.
/**
* Socket event interface extending EventEmitter
* All events are strongly typed for development safety
*/
interface SocketReservedEvents {
// Connection lifecycle events
open: () => void;
handshake: (data: HandshakeData) => void;
close: (reason: string, description?: CloseDetails | Error) => void;
error: (err: string | Error) => void;
// Data transmission events
packet: (packet: Packet) => void;
packetCreate: (packet: Packet) => void;
data: (data: RawData) => void;
message: (data: RawData) => void;
// Flow control events
drain: () => void;
flush: () => void;
// Heartbeat events
heartbeat: () => void;
ping: () => void;
pong: () => void;
// Transport upgrade events
upgrading: (transport: Transport) => void;
upgrade: (transport: Transport) => void;
upgradeError: (err: Error) => void;
}Usage Examples:
import { Socket } from "engine.io-client";
const socket = new Socket("ws://localhost:3000");
// Connection lifecycle
socket.on("open", () => {
console.log("Connection established");
});
socket.on("close", (reason, description) => {
console.log("Connection closed:", reason);
if (description) {
console.log("Details:", description);
}
});
socket.on("error", (error) => {
console.error("Socket error:", error);
});Events for monitoring connection establishment, handshake, and termination.
/**
* Connection establishment event
* Fired when the connection is successfully opened
*/
on(event: "open", listener: () => void): Socket;
/**
* Handshake completion event
* Fired after successful handshake with server
*/
on(event: "handshake", listener: (data: HandshakeData) => void): Socket;
/**
* Connection close event
* Fired when connection is closed for any reason
*/
on(event: "close", listener: (reason: string, description?: CloseDetails | Error) => void): Socket;
/**
* Error event
* Fired when an error occurs on the connection
*/
on(event: "error", listener: (err: string | Error) => void): Socket;
interface HandshakeData {
sid: string;
upgrades: string[];
pingInterval: number;
pingTimeout: number;
maxPayload: number;
}
interface CloseDetails {
description: string;
context?: unknown;
}Usage Examples:
socket.on("handshake", (data) => {
console.log("Socket ID:", data.sid);
console.log("Available upgrades:", data.upgrades);
console.log("Ping interval:", data.pingInterval);
});
socket.on("close", (reason, description) => {
switch (reason) {
case "transport close":
console.log("Transport closed connection");
break;
case "ping timeout":
console.log("Connection timed out");
break;
case "transport error":
console.log("Transport error occurred");
break;
}
});Events for handling incoming and outgoing data packets.
/**
* Raw packet event
* Fired for every packet received from server
*/
on(event: "packet", listener: (packet: Packet) => void): Socket;
/**
* Packet creation event
* Fired when a packet is created for sending
*/
on(event: "packetCreate", listener: (packet: Packet) => void): Socket;
/**
* Data event
* Fired when data message is received
*/
on(event: "data", listener: (data: RawData) => void): Socket;
/**
* Message event (alias for data)
* Fired when message is received
*/
on(event: "message", listener: (data: RawData) => void): Socket;
interface Packet {
type: PacketType;
data?: RawData;
}
type PacketType = "open" | "close" | "ping" | "pong" | "message" | "upgrade" | "noop";
type RawData = string | Buffer | ArrayBuffer | ArrayBufferView | Blob;Usage Examples:
// Handle incoming messages
socket.on("message", (data) => {
if (typeof data === "string") {
const message = JSON.parse(data);
console.log("Received JSON:", message);
} else {
console.log("Received binary data:", data);
}
});
// Monitor all packets (debugging)
socket.on("packet", (packet) => {
console.log("Packet type:", packet.type);
if (packet.data) {
console.log("Packet data:", packet.data);
}
});
// Monitor outgoing packets
socket.on("packetCreate", (packet) => {
console.log("Sending packet:", packet.type);
});Events for monitoring buffer states and flow control mechanisms.
/**
* Drain event
* Fired when write buffer becomes empty
*/
on(event: "drain", listener: () => void): Socket;
/**
* Flush event
* Fired when buffered packets are flushed
*/
on(event: "flush", listener: () => void): Socket;Usage Examples:
// Monitor buffer drainage
socket.on("drain", () => {
console.log("Write buffer drained, ready for more data");
// Safe to send more data
socket.send("More data after drain");
});
// Monitor buffer flushing
socket.on("flush", () => {
console.log("Packets flushed to transport");
});
// Check buffer state before sending
if (socket.writeBuffer.length < 10) {
socket.send("data");
} else {
console.log("Buffer full, waiting for drain");
socket.once("drain", () => {
socket.send("data");
});
}Events for monitoring connection health through ping/pong mechanism.
/**
* Heartbeat event
* Fired periodically to indicate connection health
*/
on(event: "heartbeat", listener: () => void): Socket;
/**
* Ping event
* Fired when ping is sent to server
*/
on(event: "ping", listener: () => void): Socket;
/**
* Pong event
* Fired when pong is received from server
*/
on(event: "pong", listener: () => void): Socket;Usage Examples:
// Monitor connection health
socket.on("heartbeat", () => {
console.log("Connection heartbeat");
});
// Track ping/pong timing
let pingTime: number;
socket.on("ping", () => {
pingTime = Date.now();
console.log("Ping sent");
});
socket.on("pong", () => {
const latency = Date.now() - pingTime;
console.log("Pong received, latency:", latency + "ms");
});Events for monitoring transport upgrade process and handling upgrade failures.
/**
* Upgrading event
* Fired when transport upgrade process begins
*/
on(event: "upgrading", listener: (transport: Transport) => void): Socket;
/**
* Upgrade event
* Fired when transport upgrade completes successfully
*/
on(event: "upgrade", listener: (transport: Transport) => void): Socket;
/**
* Upgrade error event
* Fired when transport upgrade fails
*/
on(event: "upgradeError", listener: (err: Error) => void): Socket;Usage Examples:
// Monitor transport upgrades
socket.on("upgrading", (transport) => {
console.log("Starting upgrade to:", transport.name);
});
socket.on("upgrade", (transport) => {
console.log("Successfully upgraded to:", transport.name);
console.log("Transport supports binary:", transport.supportsBinary);
});
socket.on("upgradeError", (error) => {
console.error("Upgrade failed:", error.message);
console.log("Continuing with current transport");
});
// Disable upgrades if problematic
socket.on("upgradeError", () => {
socket.opts.upgrade = false;
console.log("Disabled further upgrade attempts");
});Standard EventEmitter methods for managing event listeners.
/**
* Add event listener
*/
on(event: keyof SocketReservedEvents, listener: Function): Socket;
/**
* Add one-time event listener
*/
once(event: keyof SocketReservedEvents, listener: Function): Socket;
/**
* Remove event listener
*/
off(event: keyof SocketReservedEvents, listener: Function): Socket;
/**
* Remove all listeners for event
*/
removeAllListeners(event?: keyof SocketReservedEvents): Socket;
/**
* Emit event (internal use)
*/
emit(event: keyof SocketReservedEvents, ...args: any[]): boolean;Usage Examples:
// Add persistent listener
const messageHandler = (data) => {
console.log("Message:", data);
};
socket.on("message", messageHandler);
// Add one-time listener
socket.once("open", () => {
console.log("Connected for the first time");
});
// Remove specific listener
socket.off("message", messageHandler);
// Remove all message listeners
socket.removeAllListeners("message");
// Remove all listeners
socket.removeAllListeners();type SocketEventNames = keyof SocketReservedEvents;
interface Transport extends Emitter {
name: string;
supportsBinary: boolean;
query: Record<string, string>;
writable: boolean;
}