JAVASCRIPT
Client-Side API Rate Limiting with a Request Queue
Implement effective client-side API rate limiting using a JavaScript request queue to prevent exceeding server-side limits and ensure a smoother integration experience for your users.
class ApiRateLimiter {
constructor(rateLimitMs = 1000) { // Default to 1 request per second
this.rateLimitMs = rateLimitMs;
this.requestQueue = [];
this.lastRequestTime = 0;
this.isProcessing = false;
}
// Method to add a new request to the queue
async enqueueRequest(requestFn) {
return new Promise((resolve, reject) => {
this.requestQueue.push({ requestFn, resolve, reject });
this.processQueue();
});
}
// Process the queue
async processQueue() {
if (this.isProcessing || this.requestQueue.length === 0) {
return;
}
this.isProcessing = true;
const now = Date.now();
const timeSinceLastRequest = now - this.lastRequestTime;
const delay = Math.max(0, this.rateLimitMs - timeSinceLastRequest);
await new Promise(res => setTimeout(res, delay));
const { requestFn, resolve, reject } = this.requestQueue.shift();
this.lastRequestTime = Date.now();
try {
const result = await requestFn();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.isProcessing = false;
// Immediately try to process the next item if available
if (this.requestQueue.length > 0) {
this.processQueue();
}
}
}
}
// --- Example Usage ---
const apiLimiter = new ApiRateLimiter(500); // Max 2 requests per second
const mockApiCall = (id) => {
return new Promise(resolve => {
const duration = Math.random() * 500 + 100; // Simulate network latency
setTimeout(() => {
console.log(`Request ${id} completed at ${Date.now() % 10000}ms`);
resolve(`Data for ${id}`);
}, duration);
});
};
const makeLimitedCall = async (id) => {
try {
const data = await apiLimiter.enqueueRequest(() => mockApiCall(id));
console.log(`Handled response for ${id}: ${data}`);
} catch (error) {
console.error(`Error for ${id}: ${error.message}`);
}
};
console.log('Starting limited API calls...');
for (let i = 0; i < 10; i++) {
makeLimitedCall(`call-${i}`);
}
console.log('All calls enqueued.');
How it works: This JavaScript snippet implements a client-side API rate limiter using a queue. The `ApiRateLimiter` class ensures that API requests are not made faster than a specified `rateLimitMs`. Requests are added to an internal queue, and the `processQueue` method asynchronously executes them, introducing a delay between each call if necessary to adhere to the rate limit. This helps prevent exceeding server-side rate limits, reducing 429 Too Many Requests errors and ensuring smoother application behavior.