CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sockjs-client

SockJS-client is a browser JavaScript library that provides a WebSocket-like object for establishing cross-browser, full-duplex communication channels between browsers and web servers.

Pending
Overview
Eval results
Files

core-api.mddocs/

Core Connection API

The SockJS class provides the primary interface for establishing and managing WebSocket-like connections with automatic transport fallback capabilities.

Capabilities

SockJS Constructor

Creates a new SockJS connection instance with optional protocol and configuration parameters.

/**
 * Creates a new SockJS connection
 * @param {string} url - Connection URL (must be http:// or https://)
 * @param {string|string[]} [protocols] - Protocol list (reserved parameter, typically not used)
 * @param {SockJSOptions} [options] - Configuration options
 * @returns {SockJS} SockJS instance
 * @throws {TypeError} If url is not provided
 * @throws {SyntaxError} If url format is invalid or contains fragments
 * @throws {Error} If attempting insecure connection from HTTPS page
 */
function SockJS(url, protocols, options);

// Can be called with or without 'new'
const sock1 = new SockJS('https://example.com/sockjs');
const sock2 = SockJS('https://example.com/sockjs');  // Also valid

URL Requirements:

  • Must be a valid HTTP or HTTPS URL
  • Cannot contain URL fragments (#)
  • Query parameters are allowed and preserved
  • Cross-domain URLs are supported with proper server configuration

Protocol Parameter:

  • Second parameter is reserved and typically not used
  • Can be string or array of strings
  • Must not contain empty strings or duplicates
  • Used for WebSocket protocol compatibility but has no effect in SockJS

Options Object:

interface SockJSOptions {
  /** Server identifier appended to connection URL (default: random 4-digit number) */
  server?: string;
  
  /** Whitelist of allowed transports (default: all available) */
  transports?: string | string[];
  
  /** Session ID generation - number for length or function for custom generator (default: 8) */
  sessionId?: number | (() => string);
  
  /** Minimum timeout in milliseconds for transport connections (default: calculated from RTT) */
  timeout?: number;
  
  /** Transport-specific configuration options */
  transportOptions?: { [transportName: string]: any };
}

Usage Examples:

// Basic connection
const sock = new SockJS('https://api.example.com/sockjs');

// With transport restrictions
const sock = new SockJS('https://api.example.com/sockjs', null, {
  transports: ['websocket', 'xhr-streaming'],
  timeout: 10000
});

// With custom session ID generator
const sock = new SockJS('https://api.example.com/sockjs', null, {
  sessionId: () => 'custom-session-' + Date.now()
});

// With server and transport options
const sock = new SockJS('https://api.example.com/sockjs', null, {
  server: 'srv001', 
  transportOptions: {
    'xhr-streaming': { timeout: 5000 },
    'websocket': { heartbeat: 30000 }
  }
});

Instance Properties

Properties available on SockJS instances for monitoring connection state and configuration.

/**
 * The connection URL after parsing and sanitization
 * @type {string}
 * @readonly
 */
SockJS.prototype.url;

/**
 * Current connection state
 * @type {number}
 * @readonly
 * Values: 0 (CONNECTING), 1 (OPEN), 2 (CLOSING), 3 (CLOSED)
 */
SockJS.prototype.readyState;

/**
 * WebSocket extensions (always empty string for SockJS)
 * @type {string}
 * @readonly
 */
SockJS.prototype.extensions;

/**
 * Selected protocol (always empty string for SockJS)
 * @type {string}
 * @readonly
 */
SockJS.prototype.protocol;

/**
 * Name of the active transport when connected
 * @type {string|null}
 * @readonly
 * Set to transport name when connection is established, null otherwise
 */
SockJS.prototype.transport;

Property Usage Examples:

const sock = new SockJS('https://example.com/sockjs');

// Check connection state
if (sock.readyState === SockJS.CONNECTING) {
  console.log('Still connecting...');
}

// Monitor transport selection
sock.onopen = function() {
  console.log('Connected using:', sock.transport);
  console.log('Final URL:', sock.url);
};

Instance Methods

Methods for sending data and closing connections.

/**
 * Send data through the connection
 * @param {any} data - Data to send (converted to string if not already)
 * @throws {Error} If connection is not yet established (CONNECTING state)
 * @returns {void}
 * 
 * Notes:
 * - Non-string data is converted to string via toString()
 * - Objects become "[object Object]" unless properly serialized
 * - Data is sent only if connection is in OPEN state
 * - No-op if connection is CLOSING or CLOSED
 */
SockJS.prototype.send(data);

/**
 * Close the connection
 * @param {number} [code] - Close code (1000 or 3000-4999, default: 1000)
 * @param {string} [reason] - Close reason (max 123 bytes, default: "Normal closure")
 * @throws {Error} If code is invalid (not 1000 or outside 3000-4999 range)
 * @throws {SyntaxError} If reason exceeds 123 characters
 * @returns {void}
 * 
 * Notes:
 * - No-op if connection is already CLOSING or CLOSED
 * - Triggers 'close' event with wasClean=true
 */
SockJS.prototype.close(code, reason);

/**
 * Calculate round-trip timeout based on measured RTT
 * @param {number} rtt - Round-trip time in milliseconds
 * @returns {number} Calculated timeout value in milliseconds
 * 
 * Note: This is primarily for internal use but exposed as part of the API.
 * Used internally to calculate connection timeouts based on network conditions.
 * Formula: RTT > 100ms ? 4 * RTT : 300 + RTT
 */
SockJS.prototype.countRTO(rtt);

Method Usage Examples:

const sock = new SockJS('https://example.com/sockjs');

sock.onopen = function() {
  // Send different data types
  sock.send('Hello World');           // String
  sock.send(42);                      // Number -> "42"
  sock.send(JSON.stringify({id: 1})); // Proper object serialization
  
  // Close with custom code and reason
  setTimeout(() => {
    sock.close(1000, 'User requested disconnect');
  }, 5000);
};

// Handle send errors
try {
  sock.send('data'); // May throw if not connected
} catch (error) {
  console.log('Send failed:', error.message);
}

// Advanced: Calculate timeout for given RTT (internal use)
const rtt = 150; // milliseconds
const timeout = sock.countRTO(rtt); // Returns 4 * 150 = 600ms
console.log('Calculated timeout:', timeout);

Static Constants

Connection state constants matching WebSocket API.

/**
 * Connection state constants
 */
SockJS.CONNECTING = 0;  // Connection is being established
SockJS.OPEN = 1;        // Connection is open and ready
SockJS.CLOSING = 2;     // Connection is being closed
SockJS.CLOSED = 3;      // Connection is closed

/**
 * Library version string
 * @type {string}
 */
SockJS.version;  // "1.6.1"

Constants Usage:

const sock = new SockJS('https://example.com/sockjs');

// Check connection state using constants
switch (sock.readyState) {
  case SockJS.CONNECTING:
    console.log('Establishing connection...');
    break;
  case SockJS.OPEN:
    console.log('Connected and ready');
    break;
  case SockJS.CLOSING:
    console.log('Connection closing...');
    break;
  case SockJS.CLOSED:
    console.log('Connection closed');
    break;
}

// Check library version
console.log('SockJS version:', SockJS.version);

Connection Lifecycle

Understanding the connection establishment and teardown process.

Connection Establishment:

  1. Constructor validates URL and options
  2. Connection state set to CONNECTING (0)
  3. Server info retrieval begins
  4. Transport selection based on capabilities and whitelist
  5. Transport connection attempt with timeout
  6. On success: state becomes OPEN (1), open event fired
  7. On failure: fallback to next transport or connection failure

Data Transmission:

  • Only possible when readyState === SockJS.OPEN
  • All data converted to strings before transmission
  • Messages queued internally if transport is temporarily unavailable

Connection Termination:

  1. close() called or transport failure detected
  2. State becomes CLOSING (2)
  3. Transport cleanup initiated
  4. State becomes CLOSED (3)
  5. close event fired with appropriate code and reason

Usage Example - Complete Lifecycle:

const sock = new SockJS('https://example.com/sockjs');

// Monitor state changes
const logState = () => {
  const states = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
  console.log('State:', states[sock.readyState], 'Transport:', sock.transport);
};

sock.onopen = function() {
  logState(); // OPEN, websocket (or other transport)
  sock.send('Connected successfully');
};

sock.onmessage = function(e) {
  console.log('Received:', e.data);
  // Echo back
  sock.send('Echo: ' + e.data);
};

sock.onclose = function(e) {
  logState(); // CLOSED, null
  console.log('Closed:', e.code, e.reason, e.wasClean);
};

sock.onerror = function() {
  logState();
  console.log('Connection error occurred');
};

// Auto-close after 30 seconds
setTimeout(() => {
  if (sock.readyState === SockJS.OPEN) {
    sock.close(1000, 'Timeout');
  }
}, 30000);

Error Handling

The SockJS constructor and methods can throw various errors that should be handled appropriately.

Constructor Errors:

// TypeError: Missing required URL parameter
try {
  const sock = new SockJS(); // Throws TypeError
} catch (error) {
  console.log('Missing URL:', error.message);
}

// SyntaxError: Invalid URL format
try {
  const sock = new SockJS('ftp://invalid.com'); // Throws SyntaxError  
} catch (error) {
  console.log('Invalid protocol:', error.message);
}

// SyntaxError: URL contains fragment
try {
  const sock = new SockJS('https://example.com#fragment'); // Throws SyntaxError
} catch (error) {
  console.log('Fragment not allowed:', error.message);
}

// Error: Security violation
try {
  // From HTTPS page connecting to HTTP (non-localhost)
  const sock = new SockJS('http://example.com/sockjs'); // Throws Error
} catch (error) {
  console.log('Security error:', error.message);
}

// TypeError: Invalid sessionId type
try {
  const sock = new SockJS('https://example.com', null, {
    sessionId: 'invalid' // Must be number or function
  }); // Throws TypeError
} catch (error) {
  console.log('Invalid sessionId:', error.message);
}

Method Errors:

const sock = new SockJS('https://example.com/sockjs');

// send() error
try {
  sock.send('data'); // Throws if readyState is CONNECTING
} catch (error) {
  console.log('Send failed:', error.message);
}

// close() errors  
try {
  sock.close(999, 'Invalid code'); // Throws Error for invalid code
} catch (error) {
  console.log('Invalid close code:', error.message);
}

try {
  sock.close(1000, 'x'.repeat(200)); // Throws SyntaxError if reason too long
} catch (error) {
  console.log('Reason too long:', error.message);
}

// Calling close() on already closed connection
sock.close();
sock.close(); // No-op, does not throw error

Install with Tessl CLI

npx tessl i tessl/npm-sockjs-client

docs

core-api.md

events.md

index.md

transports.md

tile.json