or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-api.mdevents.mdindex.mdtransports.md

events.mddocs/

0

# Event System

1

2

SockJS implements a DOM-compatible event system that supports both traditional event handler properties (`onopen`, `onmessage`, etc.) and modern event listener methods (`addEventListener`, `removeEventListener`). This provides flexibility for different coding styles and integration patterns.

3

4

## Capabilities

5

6

### Event Handler Properties

7

8

Traditional WebSocket-style event handlers for connection lifecycle and data events.

9

10

```javascript { .api }

11

/**

12

* Event handler for connection open event

13

* @type {function|null}

14

* Called when connection is successfully established

15

*/

16

SockJS.prototype.onopen;

17

18

/**

19

* Event handler for incoming messages

20

* @type {function|null}

21

* @param {MessageEvent} event - Event object with data property

22

*/

23

SockJS.prototype.onmessage;

24

25

/**

26

* Event handler for connection close event

27

* @type {function|null}

28

* @param {CloseEvent} event - Event object with code, reason, wasClean properties

29

*/

30

SockJS.prototype.onclose;

31

32

/**

33

* Event handler for connection errors

34

* @type {function|null}

35

* Called when connection encounters an error

36

*/

37

SockJS.prototype.onerror;

38

```

39

40

**Usage Examples:**

41

42

```javascript

43

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

44

45

// Set up event handlers

46

sock.onopen = function() {

47

console.log('Connection established');

48

console.log('Using transport:', this.transport);

49

};

50

51

sock.onmessage = function(event) {

52

console.log('Received message:', event.data);

53

console.log('Event type:', event.type); // "message"

54

};

55

56

sock.onclose = function(event) {

57

console.log('Connection closed');

58

console.log('Code:', event.code);

59

console.log('Reason:', event.reason);

60

console.log('Clean close:', event.wasClean);

61

};

62

63

sock.onerror = function() {

64

console.log('Connection error occurred');

65

};

66

67

// Event handlers can be removed by setting to null

68

sock.onmessage = null;

69

```

70

71

### EventTarget Methods

72

73

Modern DOM-compatible event listener methods for more sophisticated event handling.

74

75

```javascript { .api }

76

/**

77

* Add an event listener for the specified event type

78

* @param {string} type - Event type ('open', 'message', 'close', 'error', 'heartbeat')

79

* @param {function} listener - Event handler function

80

* @returns {void}

81

*

82

* Notes:

83

* - Same listener function won't be added twice for the same event type

84

* - Listeners are called after the corresponding onXXX handler

85

*/

86

SockJS.prototype.addEventListener(type, listener);

87

88

/**

89

* Remove an event listener for the specified event type

90

* @param {string} type - Event type to remove listener from

91

* @param {function} listener - Specific listener function to remove

92

* @returns {void}

93

*

94

* Notes:

95

* - Only removes the exact function reference provided

96

* - No-op if listener was not previously added

97

*/

98

SockJS.prototype.removeEventListener(type, listener);

99

100

/**

101

* Dispatch an event to all registered listeners

102

* @param {Event} event - Event object to dispatch

103

* @returns {void}

104

*

105

* Note: Primarily for internal use, but can be used for custom events

106

*/

107

SockJS.prototype.dispatchEvent(event);

108

```

109

110

**Usage Examples:**

111

112

```javascript

113

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

114

115

// Define reusable handler functions

116

function handleOpen() {

117

console.log('Connected via addEventListener');

118

}

119

120

function handleMessage(event) {

121

console.log('Message via addEventListener:', event.data);

122

123

// Remove this listener after first message

124

sock.removeEventListener('message', handleMessage);

125

}

126

127

function handleClose(event) {

128

console.log('Closed via addEventListener:', event.code);

129

}

130

131

// Add multiple listeners

132

sock.addEventListener('open', handleOpen);

133

sock.addEventListener('message', handleMessage);

134

sock.addEventListener('close', handleClose);

135

136

// Add multiple listeners for the same event

137

sock.addEventListener('message', function(event) {

138

console.log('Second message handler:', event.data);

139

});

140

141

// Remove specific listener

142

sock.removeEventListener('open', handleOpen);

143

144

// Anonymous functions can't be removed without reference

145

const anonymousHandler = function(event) {

146

console.log('Anonymous handler:', event.data);

147

};

148

sock.addEventListener('message', anonymousHandler);

149

// Later: sock.removeEventListener('message', anonymousHandler);

150

```

151

152

### Event Types

153

154

Available event types and their characteristics.

155

156

```javascript { .api }

157

/**

158

* Event type constants and descriptions

159

*/

160

const EventTypes = {

161

'open': 'Connection successfully established',

162

'message': 'Data received from server',

163

'close': 'Connection closed (normal or error)',

164

'error': 'Connection error occurred',

165

'heartbeat': 'Heartbeat received from server'

166

};

167

```

168

169

**Event Type Details:**

170

171

1. **open**: Fired when connection moves to OPEN state

172

- No additional data in event object

173

- Safe to call `send()` after this event

174

175

2. **message**: Fired when data is received

176

- Event has `data` property with message content

177

- Data is always a string (server must send strings)

178

179

3. **close**: Fired when connection is closed

180

- Event has `code`, `reason`, and `wasClean` properties

181

- Connection cannot be reused after this event

182

183

4. **error**: Fired on connection errors

184

- Typically fired before close event

185

- No additional data in event object

186

187

5. **heartbeat**: Fired when server sends heartbeat

188

- Indicates connection is still alive

189

- No additional data in event object

190

191

**Comprehensive Event Example:**

192

193

```javascript

194

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

195

196

// Using both handler properties and addEventListener

197

sock.onopen = function() {

198

console.log('Handler property: opened');

199

};

200

201

sock.addEventListener('open', function() {

202

console.log('Event listener: opened'); // Called after onopen

203

});

204

205

// Multiple message handlers

206

const logMessage = (event) => console.log('Log:', event.data);

207

const processMessage = (event) => {

208

try {

209

const data = JSON.parse(event.data);

210

console.log('Parsed:', data);

211

} catch (e) {

212

console.log('Raw:', event.data);

213

}

214

};

215

216

sock.addEventListener('message', logMessage);

217

sock.addEventListener('message', processMessage);

218

219

// Heartbeat monitoring

220

sock.addEventListener('heartbeat', function() {

221

console.log('Heartbeat received at', new Date());

222

});

223

224

// Error and close handling

225

sock.addEventListener('error', function() {

226

console.log('Connection error detected');

227

});

228

229

sock.addEventListener('close', function(event) {

230

console.log('Connection closed:', {

231

code: event.code,

232

reason: event.reason,

233

wasClean: event.wasClean,

234

timestamp: new Date()

235

});

236

});

237

```

238

239

### Event Objects

240

241

Detailed structure of event objects passed to event handlers.

242

243

```javascript { .api }

244

/**

245

* Base event object structure

246

*/

247

interface SockJSEvent {

248

type: string; // Event type name

249

bubbles: boolean; // Always false

250

cancelable: boolean; // Always false

251

timeStamp: number; // Event creation timestamp

252

}

253

254

/**

255

* Message event object

256

*/

257

interface SockJSMessageEvent extends SockJSEvent {

258

type: 'message';

259

data: any; // Message payload (typically string)

260

}

261

262

/**

263

* Close event object

264

*/

265

interface SockJSCloseEvent extends SockJSEvent {

266

type: 'close';

267

code: number; // Close code (1000, 2xxx, 3xxx-4xxx)

268

reason: string; // Human-readable close reason

269

wasClean: boolean; // Whether close was clean (normal)

270

}

271

272

/**

273

* Simple events (open, error, heartbeat)

274

*/

275

interface SockJSSimpleEvent extends SockJSEvent {

276

type: 'open' | 'error' | 'heartbeat';

277

// No additional properties

278

}

279

```

280

281

**Event Object Usage:**

282

283

```javascript

284

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

285

286

sock.onmessage = function(event) {

287

// MessageEvent properties

288

console.log('Type:', event.type); // "message"

289

console.log('Data:', event.data); // Message content

290

console.log('Time:', event.timeStamp); // When event was created

291

console.log('Bubbles:', event.bubbles); // false

292

};

293

294

sock.onclose = function(event) {

295

// CloseEvent properties

296

console.log('Type:', event.type); // "close"

297

console.log('Code:', event.code); // Close code number

298

console.log('Reason:', event.reason); // Close reason string

299

console.log('Clean:', event.wasClean); // Clean close flag

300

console.log('Time:', event.timeStamp); // Event timestamp

301

};

302

303

sock.onopen = function(event) {

304

// Simple event properties

305

console.log('Type:', event.type); // "open"

306

console.log('Time:', event.timeStamp); // Event timestamp

307

// No data, code, reason, etc.

308

};

309

```

310

311

### Custom Event Dispatch

312

313

Advanced usage for custom event handling and testing.

314

315

```javascript { .api }

316

/**

317

* Create and dispatch custom events

318

* Note: Primarily for testing or advanced integration scenarios

319

*/

320

321

// Import event classes (internal, for reference)

322

const Event = require('sockjs-client/lib/event/event');

323

const CloseEvent = require('sockjs-client/lib/event/close');

324

const TransportMessageEvent = require('sockjs-client/lib/event/trans-message');

325

```

326

327

**Custom Event Example:**

328

329

```javascript

330

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

331

332

// Listen for custom events

333

sock.addEventListener('custom', function(event) {

334

console.log('Custom event received');

335

});

336

337

// Dispatch custom event (advanced usage)

338

sock.onopen = function() {

339

// Create custom event object

340

const customEvent = {

341

type: 'custom',

342

bubbles: false,

343

cancelable: false,

344

timeStamp: Date.now()

345

};

346

347

// Dispatch it

348

sock.dispatchEvent(customEvent);

349

};

350

```

351

352

## Event Handler Execution Order

353

354

Understanding the order in which event handlers are called.

355

356

**Execution Sequence:**

357

358

1. `onXXX` handler property (if set)

359

2. All `addEventListener` listeners in order of registration

360

3. Event processing completes

361

362

**Example Demonstrating Order:**

363

364

```javascript

365

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

366

367

// This will be called first

368

sock.onopen = function() {

369

console.log('1. onopen handler');

370

};

371

372

// These will be called in registration order after onopen

373

sock.addEventListener('open', function() {

374

console.log('2. First addEventListener');

375

});

376

377

sock.addEventListener('open', function() {

378

console.log('3. Second addEventListener');

379

});

380

381

// Output when connection opens:

382

// 1. onopen handler

383

// 2. First addEventListener

384

// 3. Second addEventListener

385

```

386

387

## Event Handling Best Practices

388

389

Recommended patterns for robust event handling.

390

391

**Basic Pattern:**

392

393

```javascript

394

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

395

396

sock.onopen = function() {

397

console.log('Connected');

398

// Connection is ready, safe to send

399

sock.send(JSON.stringify({type: 'init'}));

400

};

401

402

sock.onmessage = function(event) {

403

try {

404

const message = JSON.parse(event.data);

405

handleMessage(message);

406

} catch (error) {

407

console.log('Invalid JSON received:', event.data);

408

}

409

};

410

411

sock.onclose = function(event) {

412

console.log('Disconnected:', event.code, event.reason);

413

414

// Reconnection logic

415

if (event.code !== 1000) {

416

setTimeout(() => reconnect(), 5000);

417

}

418

};

419

420

sock.onerror = function() {

421

console.log('Connection error');

422

// Error handling logic

423

};

424

```

425

426

**Advanced Pattern with Cleanup:**

427

428

```javascript

429

function createConnection(url) {

430

const sock = new SockJS(url);

431

const handlers = new Set();

432

433

// Helper to add removable listeners

434

const addListener = (type, handler) => {

435

sock.addEventListener(type, handler);

436

handlers.add(() => sock.removeEventListener(type, handler));

437

};

438

439

// Set up handlers

440

addListener('open', handleOpen);

441

addListener('message', handleMessage);

442

addListener('close', handleClose);

443

addListener('error', handleError);

444

445

// Cleanup function

446

const cleanup = () => {

447

handlers.forEach(remove => remove());

448

handlers.clear();

449

};

450

451

return { sock, cleanup };

452

}

453

454

// Usage

455

const { sock, cleanup } = createConnection('https://example.com/sockjs');

456

457

// Later: cleanup when done

458

cleanup();

459

```