Configuring Axios with WebSockets and Fallback Polling
This article explains how to integrate the Axios HTTP client into real-time architectures that utilize WebSockets and fallback polling mechanisms. Because Axios is strictly an HTTP client that operates on standard request-response protocols, it cannot establish persistent WebSocket connections on its own. Instead, Axios plays a crucial role in authenticating real-time sessions, executing long or short polling when WebSockets are unsupported or blocked, and managing graceful degradation strategies.
The Role of Axios in Real-Time Architectures
WebSockets operate over the ws:// or wss://
protocols, providing full-duplex communication channels over a single
TCP connection. Axios operates exclusively over http:// and
https://.
In modern web applications, Axios complements WebSocket implementations in three primary ways:
- Authentication and Handshaking: Fetching short-lived session tokens or connection URLs via HTTP before initiating the WebSocket handshake.
- Fallback Polling: Handling short or long polling requests when firewalls, proxies, or legacy environments block WebSocket upgrades.
- Data Hydration: Fetching the initial state via standard REST endpoints before subscribing to incremental WebSocket updates.
Implementing Long Polling with Axios
When a WebSocket connection fails, long polling is the most common HTTP-based alternative. In long polling, the client sends an HTTP request to the server, which holds the request open until new data is available or a timeout occurs.
Axios Configuration for Long Polling
To implement reliable long polling, Axios must be configured with
custom timeout thresholds and cancellation handling using
AbortController.
import axios from 'axios';
class PollingService {
constructor(endpoint, interval = 5000) {
this.endpoint = endpoint;
this.interval = interval;
this.isPolling = false;
this.abortController = null;
}
async startPolling(onDataReceived) {
this.isPolling = true;
while (this.isPolling) {
this.abortController = new AbortController();
try {
const response = await axios.get(this.endpoint, {
signal: this.abortController.signal,
timeout: 30000, // Keep connection open for up to 30 seconds
headers: {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
}
});
if (response.status === 200 && response.data) {
onDataReceived(response.data);
}
} catch (error) {
if (axios.isCancel(error)) {
break; // Polling intentionally stopped
}
// Handle network errors or server timeouts
console.error('Polling error, retrying...', error.message);
await new Promise((resolve) => setTimeout(resolve, this.interval));
}
}
}
stopPolling() {
this.isPolling = false;
if (this.abortController) {
this.abortController.abort();
}
}
}
export default PollingService;Creating a Hybrid WebSocket and Axios Fallback Manager
A unified client abstraction allows an application to automatically attempt a WebSocket connection and fallback to Axios-based polling if the connection drops or fails.
import axios from 'axios';
class RealtimeClient {
constructor(wsUrl, pollUrl) {
this.wsUrl = wsUrl;
this.pollUrl = pollUrl;
this.socket = null;
this.pollingActive = false;
this.abortController = null;
this.listeners = [];
}
subscribe(callback) {
this.listeners.push(callback);
}
notify(data) {
this.listeners.forEach((listener) => listener(data));
}
connect() {
try {
this.socket = new WebSocket(this.wsUrl);
this.socket.onopen = () => {
console.log('WebSocket connected');
this.stopPollingFallback();
};
this.socket.onmessage = (event) => {
const data = JSON.parse(event.data);
this.notify(data);
};
this.socket.onerror = () => {
console.warn('WebSocket error encountered. Switching to polling fallback.');
this.socket.close();
};
this.socket.onclose = () => {
if (!this.pollingActive) {
this.startPollingFallback();
}
};
} catch (e) {
this.startPollingFallback();
}
}
async startPollingFallback() {
this.pollingActive = true;
console.log('Fallback polling started via Axios');
while (this.pollingActive) {
this.abortController = new AbortController();
try {
const response = await axios.get(this.pollUrl, {
signal: this.abortController.signal,
timeout: 10000
});
if (response.data) {
this.notify(response.data);
}
// Standard delay between short-polling cycles
await new Promise((resolve) => setTimeout(resolve, 3000));
} catch (error) {
if (axios.isCancel(error)) {
break;
}
await new Promise((resolve) => setTimeout(resolve, 5000));
}
}
}
stopPollingFallback() {
this.pollingActive = false;
if (this.abortController) {
this.abortController.abort();
}
}
disconnect() {
if (this.socket) {
this.socket.close();
}
this.stopPollingFallback();
}
}Essential Axios Settings for Fallback Strategies
When configuring Axios specifically for fallback operations, apply these settings:
timeout: Set this higher than normal for long polling (e.g., 25000 to 60000 ms) to avoid prematurely closing idle long-poll connections, or keep it short (e.g., 5000 ms) for rapid short polling.signal: Always bind anAbortSignalto allow the application to immediately tear down network traffic when navigating away or reconnecting to a primary WebSocket.validateStatus: ConfigurevalidateStatus: (status) => status >= 200 && status < 300 || status === 304to properly handle HTTP 304 (Not Modified) responses during polling loops.- Interceptors: Use
axios.interceptors.responseto capture HTTP401 Unauthorizederrors during polling, allowing authentication token refresh routines to run before resuming real-time data ingestion.