Pusher Channels JavaScript library for browsers, React Native, NodeJS and web workers
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Low-level connection management with WebSocket handling, automatic reconnection, transport fallback, and connection state monitoring.
Core connection management class handling WebSocket connections and transport strategies.
/**
* Manages WebSocket connections with automatic reconnection and fallback
* Extends EventsDispatcher for connection state events
*/
class ConnectionManager extends EventsDispatcher {
// Properties
key: string;
options: ConnectionManagerOptions;
state: string;
connection: Connection;
usingTLS: boolean;
timeline: Timeline;
socket_id: string;
activityTimeout: number;
strategy: Strategy;
runner: StrategyRunner;
// Timers
unavailableTimer: Timer;
activityTimer: Timer;
retryTimer: Timer;
// Configuration
activityTimeout: number;
strategy: Strategy;
runner: StrategyRunner;
// Callbacks
errorCallbacks: ErrorCallbacks;
handshakeCallbacks: HandshakeCallbacks;
connectionCallbacks: ConnectionCallbacks;
constructor(key: string, options: ConnectionManagerOptions);
// Connection Control
connect(): void;
disconnect(): void;
// Data Transmission
send(data: any): boolean;
send_event(name: string, data: any, channel?: string): boolean;
// State Information
isUsingTLS(): boolean;
// Internal Methods (typically not used directly)
tryConnect(): void;
abortConnection(): void;
clearAllTimeouts(): void;
clearTimeout(timer: Timer): void;
scheduleConnect(): void;
}Connection Manager Examples:
// Access connection manager from Pusher instance
const pusher = new Pusher("app-key", { cluster: "us2" });
const connectionManager = pusher.connection;
// Monitor connection state
console.log("Current state:", connectionManager.state);
console.log("Socket ID:", connectionManager.socket_id);
console.log("Using TLS:", connectionManager.isUsingTLS());
// Manual connection control (usually automatic)
connectionManager.connect();
connectionManager.disconnect();
// Send raw data (usually use higher-level methods)
connectionManager.send(JSON.stringify({
event: "pusher:ping",
data: {}
}));
// Send event through connection
connectionManager.send_event("client-event", { message: "hello" }, "my-channel");Configuration options for connection management.
/**
* Connection manager configuration options
*/
interface ConnectionManagerOptions {
getStrategy: (options: StrategyOptions) => Strategy;
timeline: Timeline;
activityTimeout: number;
pongTimeout: number;
unavailableTimeout: number;
useTLS: boolean;
}
/**
* Strategy options for connection methods
*/
interface StrategyOptions {
useTLS: boolean;
hostNonTLS: string;
hostTLS: string;
httpPort: number;
httpsPort: number;
wsPort: number;
wssPort: number;
enableStats: boolean;
timelineParams?: any;
}Connection state enumeration and transitions.
// Connection states (string values)
type ConnectionState =
| "initialized" // Initial state
| "connecting" // Attempting to connect
| "connected" // Successfully connected
| "unavailable" // Service unavailable
| "failed" // Connection failed
| "disconnected"; // Disconnected
// State transition events
interface StateChangeEvent {
previous: ConnectionState;
current: ConnectionState;
}Connection State Examples:
const pusher = new Pusher("app-key", { cluster: "us2" });
// Monitor state changes
pusher.connection.bind("state_change", (states) => {
console.log(`State changed from ${states.previous} to ${states.current}`);
switch (states.current) {
case "connecting":
showConnectingIndicator();
break;
case "connected":
hideConnectingIndicator();
console.log("Socket ID:", pusher.connection.socket_id);
break;
case "disconnected":
showOfflineIndicator();
break;
case "failed":
showConnectionFailedError();
break;
}
});
// Check current state
if (pusher.connection.state === "connected") {
console.log("Ready to send messages");
}Callback interfaces for handling connection events.
/**
* Error handling callbacks
*/
interface ErrorCallbacks {
tls_only?: () => void;
refused?: () => void;
backoff?: () => void;
retry?: () => void;
}
/**
* Handshake event callbacks
*/
interface HandshakeCallbacks {
ssl_only?: () => void;
succeeded?: (data: any) => void;
failed?: (error: any) => void;
}
/**
* Connection event callbacks
*/
interface ConnectionCallbacks {
message?: (event: any) => void;
ping?: () => void;
pong?: () => void;
error?: (error: any) => void;
closed?: () => void;
}Callback Examples:
const pusher = new Pusher("app-key", { cluster: "us2" });
// Connection-level event handling (usually done through pusher.bind)
pusher.connection.bind("message", (event) => {
console.log("Received message:", event);
});
pusher.connection.bind("error", (error) => {
console.error("Connection error:", error);
});
pusher.connection.bind("closed", () => {
console.log("Connection closed");
});Transport and strategy configuration for connection fallbacks.
/**
* Available transport types
*/
type Transport =
| "ws" // WebSocket
| "wss" // Secure WebSocket
| "xhr_polling" // XHR long polling
| "xhr_streaming" // XHR streaming
| "sockjs" // SockJS fallback
| "jsonp"; // JSONP polling
/**
* Transport configuration in options
*/
interface TransportOptions {
enabledTransports?: Transport[];
disabledTransports?: Transport[];
// Timeout configurations
activityTimeout?: number; // Activity timeout (default: 120000ms)
pongTimeout?: number; // Pong response timeout (default: 30000ms)
unavailableTimeout?: number; // Unavailable timeout (default: 10000ms)
}Transport Configuration Examples:
// Enable specific transports only
const pusher = new Pusher("app-key", {
cluster: "us2",
enabledTransports: ["ws", "wss"],
disabledTransports: ["xhr_polling", "sockjs"]
});
// Configure timeouts
const pusher = new Pusher("app-key", {
cluster: "us2",
activityTimeout: 30000, // 30 seconds
pongTimeout: 6000, // 6 seconds
unavailableTimeout: 5000 // 5 seconds
});
// Force specific transport behavior
const pusher = new Pusher("app-key", {
cluster: "us2",
forceTLS: true, // Only use secure transports
enabledTransports: ["wss"] // WebSocket Secure only
});Built-in events for connection state monitoring.
Connection State Events:
// Core connection events
pusher.connection.bind("connecting", () => {
console.log("Attempting to connect...");
});
pusher.connection.bind("connected", () => {
console.log("Successfully connected");
console.log("Socket ID:", pusher.connection.socket_id);
});
pusher.connection.bind("disconnected", () => {
console.log("Disconnected from Pusher");
});
pusher.connection.bind("unavailable", () => {
console.log("Pusher service unavailable");
});
pusher.connection.bind("failed", () => {
console.log("Connection failed permanently");
});
pusher.connection.bind("reconnecting", () => {
console.log("Attempting to reconnect...");
});
pusher.connection.bind("reconnected", () => {
console.log("Successfully reconnected");
});Protocol Events:
// Low-level protocol events
pusher.connection.bind("message", (event) => {
console.log("Raw message received:", event);
});
pusher.connection.bind("ping", () => {
console.log("Ping received from server");
});
pusher.connection.bind("pong", () => {
console.log("Pong sent to server");
});
pusher.connection.bind("error", (error) => {
console.error("Protocol error:", error);
});Advanced features for connection monitoring and control.
/**
* Timer classes for connection management
*/
class OneOffTimer {
constructor(delay: number, callback: () => void);
ensureAborted(): void;
}
class PeriodicTimer {
constructor(delay: number, callback: () => void);
ensureAborted(): void;
}
/**
* Timeline for connection event tracking
*/
interface TimelineOptions {
cluster?: string;
features?: string[];
params?: any;
limit?: number;
level?: TimelineLevel;
version?: string;
}
class Timeline {
constructor(key: string, session: number, options: TimelineOptions);
info(event: any): void;
debug(event: any): void;
warn(event: any): void;
error(event: any): void;
}Advanced Usage Examples:
// Custom connection strategy (advanced)
const pusher = new Pusher("app-key", {
cluster: "us2",
// Custom host configuration
wsHost: "ws-custom.pusherapp.com",
wsPort: 80,
wssPort: 443,
httpHost: "sockjs-custom.pusherapp.com",
httpPort: 80,
httpsPort: 443,
// Enable connection stats
enableStats: true,
statsHost: "stats.pusherapp.com"
});
// Monitor connection timeline (if enabled)
pusher.timeline.info({
event: "custom_connection_event",
data: { custom: "data" }
});
// Access connection timers (read-only, for monitoring)
const connection = pusher.connection;
console.log("Activity timer active:", connection.activityTimer !== null);
console.log("Retry timer active:", connection.retryTimer !== null);Platform-specific network state detection.
/**
* Reachability interface for network detection
*/
interface Reachability {
isOnline(): boolean;
bind(event: string, callback: Function): void;
unbind(event?: string, callback?: Function): void;
}Network State Examples:
// Network state events (platform-dependent)
pusher.bind("online", () => {
console.log("Network came online, reconnecting...");
});
pusher.bind("offline", () => {
console.log("Network went offline");
});
// Manual network state check (if available)
if (typeof navigator !== 'undefined' && navigator.onLine !== undefined) {
console.log("Browser online:", navigator.onLine);
}// Enable debug logging
Pusher.logToConsole = true;
// Custom logging for debugging
Pusher.log = (message) => {
console.log(`[Pusher Debug] ${new Date().toISOString()}:`, message);
};
// Monitor connection attempts
let connectionAttempts = 0;
pusher.connection.bind("connecting", () => {
connectionAttempts++;
console.log(`Connection attempt #${connectionAttempts}`);
});
pusher.connection.bind("error", (error) => {
console.error("Connection error details:", {
error,
state: pusher.connection.state,
socketId: pusher.connection.socket_id,
attempts: connectionAttempts
});
});
// Connection health check
function checkConnectionHealth() {
const state = pusher.connection.state;
const socketId = pusher.connection.socket_id;
return {
connected: state === "connected",
state,
socketId,
usingTLS: pusher.connection.isUsingTLS(),
timestamp: new Date().toISOString()
};
}
// Periodic health monitoring
setInterval(() => {
console.log("Connection health:", checkConnectionHealth());
}, 30000);// Force reconnection
function forceReconnect() {
console.log("Forcing reconnection...");
pusher.disconnect();
setTimeout(() => {
pusher.connect();
}, 1000);
}
// Exponential backoff reconnection
let reconnectAttempts = 0;
pusher.connection.bind("disconnected", () => {
const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
console.log(`Reconnecting in ${delay}ms (attempt ${reconnectAttempts + 1})`);
setTimeout(() => {
reconnectAttempts++;
pusher.connect();
}, delay);
});
pusher.connection.bind("connected", () => {
reconnectAttempts = 0; // Reset on successful connection
});Install with Tessl CLI
npx tessl i tessl/npm-pusher-js