JAVASCRIPT

Manage API Request Rates with a Simple Delay Queue (JavaScript)

Implement a basic client-side request queue with a configurable delay to prevent exceeding API rate limits and ensure smooth, controlled data fetching.

/**
 * A simple rate-limiting queue for API requests.
 * Processes requests sequentially with a minimum delay between each.
 */
class RateLimiterQueue {
  constructor(delayMs = 1000) {
    this.queue = [];
    this.delayMs = delayMs;
    this.isProcessing = false;
  }

  /**
   * Adds an API request function to the queue.
   * The function should return a Promise.
   *
   * @param {Function} requestFn A function that executes an API call and returns a Promise.
   * @returns {Promise<any>} A promise that resolves with the result of the API call.
   */
  enqueue(requestFn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ requestFn, resolve, reject });
      this.processQueue();
    });
  }

  async processQueue() {
    if (this.isProcessing || this.queue.length === 0) {
      return;
    }

    this.isProcessing = true;
    const { requestFn, resolve, reject } = this.queue.shift();

    try {
      const result = await requestFn();
      resolve(result);
    } catch (error) {
      reject(error);
    } finally {
      // Wait for the specified delay before processing the next item
      await new Promise(res => setTimeout(res, this.delayMs));
      this.isProcessing = false;
      // Recursively call processQueue to handle the next item if any
      this.processQueue();
    }
  }
}

// --- Example Usage ---
const apiLimiter = new RateLimiterQueue(500); // 500ms delay between requests

async function fetchUserData(userId) {
  // Simulate an API call
  console.log(`[${new Date().toLocaleTimeString()}] Fetching user ${userId}...`);
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`[${new Date().toLocaleTimeString()}] Fetched user ${userId}.`);
      resolve({ id: userId, name: `User ${userId}`, data: Math.random() });
    }, Math.random() * 500 + 200); // Simulate variable API response time
  });
}

// Enqueue multiple requests
apiLimiter.enqueue(() => fetchUserData(1))
  .then(data => console.log('Result 1:', data))
  .catch(error => console.error('Error 1:', error));

apiLimiter.enqueue(() => fetchUserData(2))
  .then(data => console.log('Result 2:', data))
  .catch(error => console.error('Error 2:', error));

apiLimiter.enqueue(() => fetchUserData(3))
  .then(data => console.log('Result 3:', data))
  .catch(error => console.error('Error 3:', error));

// You can add more requests dynamically
setTimeout(() => {
  apiLimiter.enqueue(() => fetchUserData(4))
    .then(data => console.log('Result 4:', data))
    .catch(error => console.error('Error 4:', error));
}, 1500);
How it works: This JavaScript snippet provides a `RateLimiterQueue` class to manage the frequency of API requests. It enqueues API call functions and processes them sequentially, introducing a configurable delay between each request. This client-side strategy helps prevent applications from inadvertently exceeding API rate limits, ensuring a smoother interaction with external services and avoiding temporary bans.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs