w3resource

Control Concurrent API Requests with JavaScript Throttling Techniques


Simulating a Throttled API:

Write a JavaScript function that ensures only a specified number of asynchronous requests are made simultaneously.

Solution-1: Implementing Throttling Using a Queue

Code:

// Function to simulate an API request
const apiRequest = (id, time) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`Request ${id} completed in ${time}ms`);
    }, time);
  });
};

// Throttled execution function
const throttledAPI = (requests, maxConcurrent) => {
  const results = [];
  let running = 0;
  let currentIndex = 0;

  return new Promise((resolve) => {
    // Function to process the next request
    const processNext = () => {
      if (currentIndex >= requests.length && running === 0) {
        resolve(results); // Resolve when all requests are processed
        return;
      }

      if (running < maxConcurrent && currentIndex < requests.length) {
        running++; // Increment running count
        const index = currentIndex;
        const request = requests[currentIndex];
        currentIndex++; // Move to the next request

        request().then((result) => {
          results[index] = result; // Store the result
          running--; // Decrement running count
          processNext(); // Trigger the next request
        });
      }
    };

    // Start the initial batch
    for (let i = 0; i < maxConcurrent; i++) {
      processNext();
    }
  });
};

// Create an array of simulated API requests
const requests = [
  () => apiRequest(1, 1000),
  () => apiRequest(2, 500),
  () => apiRequest(3, 1500),
  () => apiRequest(4, 100),
  () => apiRequest(5, 2000),
];

// Run the throttled API with a limit of 2 concurrent requests
throttledAPI(requests, 2).then((results) => {
  console.log("Results:", results); // Logs results in order
});

Output:

"Results:"
["Request 1 completed in 1000ms", "Request 2 completed in 500ms", "Request 3 completed in 1500ms", "Request 4 completed in 100ms", "Request 5 completed in 2000ms"]

Explanation:

  • API Simulation: apiRequest simulates an asynchronous API call.
  • Queue Mechanism: Maintains a queue of pending requests and processes a maximum number (maxConcurrent) concurrently.
  • Sequential Processing: Uses a loop and processNext function to control the flow.
  • Completion: Resolves the results once all requests are processed.

Solution-2: Throttling Using Promise.all

Code:

// Function to simulate an API request
const apiRequest = (id, time) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`Request ${id} completed in ${time}ms`);
    }, time);
  });
};

// Function to run requests with throttling
const throttledAPI = async (requests, maxConcurrent) => {
  const results = [];
  const executing = new Set();

  for (const request of requests) {
    const promise = request().then((result) => {
      executing.delete(promise); // Remove completed request from executing
      return result;
    });

    executing.add(promise); // Add request to executing
    results.push(promise);

    if (executing.size >= maxConcurrent) {
      await Promise.race(executing); // Wait for one request to finish
    }
  }

  return Promise.all(results); // Wait for all requests to finish
};

// Create an array of simulated API requests
const requests = [
  () => apiRequest(1, 1000),
  () => apiRequest(2, 500),
  () => apiRequest(3, 1500),
  () => apiRequest(4, 100),
  () => apiRequest(5, 2000),
];

// Run the throttled API with a limit of 2 concurrent requests
throttledAPI(requests, 2).then((results) => {
  console.log("Results:", results); // Logs results in order
});

Output:

"Results:"
["Request 1 completed in 1000ms", "Request 2 completed in 500ms"]

Explanation:

  • API Simulation: Same as Solution 1.
  • Promise Set: Tracks active requests using a Set to handle concurrency.
  • Throttling with Promise.race: Waits for one active request to finish before starting the next.
  • Completion: Uses Promise.all to ensure all requests complete.

See the Pen promises-and-async-await-exercise-9 by w3resource (@w3resource) on CodePen.


Improve this sample solution and post your code through Disqus

Previous: Error Handling in Async/Await Functions with Try...Catch in JavaScript.
Next: Wrapping Asynchronous operations in JavaScript Promises.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.