Master real-time communication with WebSockets. Learn bidirectional data transfer, live updates, and building responsive real-time applications.
WebSockets enable real-time, bidirectional communication between the browser and server. Unlike traditional HTTP requests that follow a request-response pattern, WebSockets maintain an open connection that allows both client and server to send data at any time.
WebSockets provide full-duplex communication channels over a single TCP connection, making them ideal for real-time applications.
WebSocket vs HTTP:
HTTP (Request-Response):
WebSocket (Persistent Connection):
Basic WebSocket Usage:
1// Create WebSocket connection
2const socket = new WebSocket('ws://localhost:8080/socket');
3
4// Connection opened
5socket.addEventListener('open', function (event) {
6 console.log('Connected to WebSocket server');
7 socket.send('Hello Server!');
8});
9
10// Listen for messages
11socket.addEventListener('message', function (event) {
12 console.log('Message from server:', event.data);
13});
14
15// Handle errors
16socket.addEventListener('error', function (error) {
17 console.error('WebSocket error:', error);
18});
19
20// Connection closed
21socket.addEventListener('close', function (event) {
22 console.log('WebSocket connection closed');
23 if (event.wasClean) {
24 console.log('Connection closed cleanly');
25 } else {
26 console.log('Connection lost');
27 }
28});Sending Different Data Types:
1// Send text
2socket.send('Hello World');
3
4// Send JSON
5const data = { type: 'message', content: 'Hello', timestamp: Date.now() };
6socket.send(JSON.stringify(data));
7
8// Send binary data
9const buffer = new ArrayBuffer(8);
10const view = new DataView(buffer);
11view.setFloat64(0, Math.PI);
12socket.send(buffer);WebSockets enable various real-time features like live chat, notifications, collaborative editing, and live data feeds.
Live Chat Implementation:
1class ChatClient {
2 constructor(serverUrl, username) {
3 this.serverUrl = serverUrl;
4 this.username = username;
5 this.socket = null;
6 this.reconnectAttempts = 0;
7 this.maxReconnectAttempts = 5;
8 }
9
10 connect() {
11 try {
12 this.socket = new WebSocket(this.serverUrl);
13 this.setupEventListeners();
14 } catch (error) {
15 console.error('Failed to create WebSocket connection:', error);
16 this.handleReconnect();
17 }
18 }
19
20 setupEventListeners() {
21 this.socket.onopen = (event) => {
22 console.log('Connected to chat server');
23 this.reconnectAttempts = 0;
24
25 // Send join message
26 this.sendMessage({
27 type: 'join',
28 username: this.username,
29 timestamp: new Date().toISOString()
30 });
31 };
32
33 this.socket.onmessage = (event) => {
34 try {
35 const message = JSON.parse(event.data);
36 this.handleMessage(message);
37 } catch (error) {
38 console.error('Failed to parse message:', error);
39 }
40 };
41
42 this.socket.onclose = (event) => {
43 console.log('Chat connection closed');
44 if (!event.wasClean) {
45 this.handleReconnect();
46 }
47 };
48
49 this.socket.onerror = (error) => {
50 console.error('Chat connection error:', error);
51 };
52 }
53
54 sendMessage(message) {
55 if (this.socket && this.socket.readyState === WebSocket.OPEN) {
56 this.socket.send(JSON.stringify(message));
57 } else {
58 console.error('Socket not connected');
59 }
60 }
61
62 sendChatMessage(text) {
63 this.sendMessage({
64 type: 'chat',
65 username: this.username,
66 text: text,
67 timestamp: new Date().toISOString()
68 });
69 }
70
71 handleMessage(message) {
72 switch (message.type) {
73 case 'chat':
74 this.displayChatMessage(message);
75 break;
76 case 'join':
77 this.displayUserJoined(message);
78 break;
79 case 'leave':
80 this.displayUserLeft(message);
81 break;
82 case 'userList':
83 this.updateUserList(message.users);
84 break;
85 default:
86 console.log('Unknown message type:', message.type);
87 }
88 }
89
90 displayChatMessage(message) {
91 const chatContainer = document.getElementById('chat-messages');
92 const messageElement = document.createElement('div');
93 messageElement.className = 'chat-message';
94 messageElement.innerHTML = `
95 <span class="username">${message.username}:</span>
96 <span class="text">${message.text}</span>
97 <span class="timestamp">${new Date(message.timestamp).toLocaleTimeString()}</span>
98 `;
99 chatContainer.appendChild(messageElement);
100 chatContainer.scrollTop = chatContainer.scrollHeight;
101 }
102
103 handleReconnect() {
104 if (this.reconnectAttempts < this.maxReconnectAttempts) {
105 this.reconnectAttempts++;
106 const delay = Math.pow(2, this.reconnectAttempts) * 1000; // Exponential backoff
107
108 console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
109
110 setTimeout(() => {
111 this.connect();
112 }, delay);
113 } else {
114 console.error('Max reconnection attempts reached');
115 }
116 }
117
118 disconnect() {
119 if (this.socket) {
120 this.socket.close();
121 }
122 }
123}
124
125// Usage
126const chat = new ChatClient('ws://localhost:8080/chat', 'john_doe');
127chat.connect();
128
129// Send message when form is submitted
130document.getElementById('chat-form').addEventListener('submit', (e) => {
131 e.preventDefault();
132 const input = document.getElementById('message-input');
133 chat.sendChatMessage(input.value);
134 input.value = '';
135});Production WebSocket applications require robust connection management, message queuing, and error recovery strategies.
Connection Manager with Auto-Reconnect:
1class WebSocketManager {
2 constructor(url, options = {}) {
3 this.url = url;
4 this.options = {
5 maxReconnectAttempts: 5,
6 reconnectDelay: 1000,
7 heartbeatInterval: 30000,
8 ...options
9 };
10
11 this.socket = null;
12 this.reconnectAttempts = 0;
13 this.heartbeatTimer = null;
14 this.messageQueue = [];
15 this.eventListeners = {};
16 this.isConnected = false;
17 }
18
19 connect() {
20 return new Promise((resolve, reject) => {
21 try {
22 this.socket = new WebSocket(this.url);
23 this.setupSocketListeners(resolve, reject);
24 } catch (error) {
25 reject(error);
26 }
27 });
28 }
29
30 setupSocketListeners(resolve, reject) {
31 this.socket.onopen = () => {
32 console.log('WebSocket connected');
33 this.isConnected = true;
34 this.reconnectAttempts = 0;
35 this.startHeartbeat();
36 this.processMessageQueue();
37 this.emit('connected');
38 resolve();
39 };
40
41 this.socket.onmessage = (event) => {
42 try {
43 const message = JSON.parse(event.data);
44
45 // Handle heartbeat pong
46 if (message.type === 'pong') {
47 return;
48 }
49
50 this.emit('message', message);
51 } catch (error) {
52 console.error('Failed to parse message:', error);
53 this.emit('error', error);
54 }
55 };
56
57 this.socket.onclose = (event) => {
58 console.log('WebSocket disconnected');
59 this.isConnected = false;
60 this.stopHeartbeat();
61 this.emit('disconnected', event);
62
63 if (!event.wasClean && this.shouldReconnect()) {
64 this.attemptReconnect();
65 }
66 };
67
68 this.socket.onerror = (error) => {
69 console.error('WebSocket error:', error);
70 this.emit('error', error);
71 reject(error);
72 };
73 }
74
75 send(data) {
76 const message = typeof data === 'string' ? data : JSON.stringify(data);
77
78 if (this.isConnected && this.socket.readyState === WebSocket.OPEN) {
79 this.socket.send(message);
80 } else {
81 // Queue message for later
82 this.messageQueue.push(message);
83 console.log('Message queued (not connected)');
84 }
85 }
86
87 processMessageQueue() {
88 while (this.messageQueue.length > 0 && this.isConnected) {
89 const message = this.messageQueue.shift();
90 this.socket.send(message);
91 }
92 }
93
94 startHeartbeat() {
95 this.heartbeatTimer = setInterval(() => {
96 if (this.isConnected) {
97 this.send({ type: 'ping', timestamp: Date.now() });
98 }
99 }, this.options.heartbeatInterval);
100 }
101
102 stopHeartbeat() {
103 if (this.heartbeatTimer) {
104 clearInterval(this.heartbeatTimer);
105 this.heartbeatTimer = null;
106 }
107 }
108
109 shouldReconnect() {
110 return this.reconnectAttempts < this.options.maxReconnectAttempts;
111 }
112
113 attemptReconnect() {
114 this.reconnectAttempts++;
115 const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
116
117 console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
118
119 setTimeout(() => {
120 this.connect().catch(error => {
121 console.error('Reconnection failed:', error);
122 });
123 }, delay);
124 }
125
126 on(event, callback) {
127 if (!this.eventListeners[event]) {
128 this.eventListeners[event] = [];
129 }
130 this.eventListeners[event].push(callback);
131 }
132
133 off(event, callback) {
134 if (this.eventListeners[event]) {
135 this.eventListeners[event] = this.eventListeners[event]
136 .filter(cb => cb !== callback);
137 }
138 }
139
140 emit(event, data) {
141 if (this.eventListeners[event]) {
142 this.eventListeners[event].forEach(callback => {
143 try {
144 callback(data);
145 } catch (error) {
146 console.error('Event listener error:', error);
147 }
148 });
149 }
150 }
151
152 disconnect() {
153 this.stopHeartbeat();
154 if (this.socket) {
155 this.socket.close();
156 }
157 }
158}
159
160// Usage
161const wsManager = new WebSocketManager('ws://localhost:8080/ws', {
162 maxReconnectAttempts: 10,
163 reconnectDelay: 1000,
164 heartbeatInterval: 30000
165});
166
167// Set up event listeners
168wsManager.on('connected', () => {
169 console.log('WebSocket manager connected');
170});
171
172wsManager.on('message', (message) => {
173 console.log('Received message:', message);
174});
175
176wsManager.on('disconnected', () => {
177 console.log('WebSocket manager disconnected');
178});
179
180// Connect
181wsManager.connect();
182
183// Send messages
184wsManager.send({ type: 'subscribe', channel: 'general' });
185wsManager.send({ type: 'message', text: 'Hello WebSocket!' });Your progress is saved in this browser, on this device only.