JavaScript Interview Questions
  • JavaScript Interview Questions
  • Contact
  • Introduction
  • Question 1
  • Question 2
  • Question 3
  • Question 4
  • Question 5
  • Question 6
  • Question 7
  • Question 8
  • Question 9
  • Question 10
  • Question 11
  • Question 12
  • Question 13
  • Question 14
  • Question 15
  • Question 16
  • Question 17
  • Question 18
  • Question 19
  • Question 20
  • Question 21
  • Question 22
  • Question 23
  • Question 24
  • Question 25
  • Question 26
  • Question 27
  • Question 28
  • Question 29
  • Question 30
  • Question 31
  • Question 32
  • Question 33
  • Question 34
  • Question 35
  • Question 36
  • Question 37
  • Question 38
  • Question 39
  • Question 40
  • Question 41
  • Question 42
  • Question 43
  • Question 44
  • Question 45
  • Question 46
  • Question 47
  • Question 48
  • Question 49
  • Question 50
  • Question 51
  • Question 52
  • Question 53
  • Question 54
  • Question 55
  • Question 56
  • Question 57
  • Question 58
  • Question 59
  • Question 60
  • Question 61
  • Question 62
  • Question 63
  • Question 64
  • Question 65
  • Question 66
  • Question 67
  • Question 68
  • Question 69
  • Question 70
  • Question 71
  • Question 72
  • Question 73
  • Question 74
  • Question 75
  • Question 76
  • Question 77
  • Question 78
  • Question 79
  • Question 80
  • Question 81
  • Question 82
  • Question 83
  • Question 84
  • Question 85
  • Question 86
  • Question 87
  • Question 88
  • Question 89
  • Question 90
  • Question 91
  • Question 92
  • Question 93
  • Question 94
  • Question 95
  • Question 96
  • Question 97
  • Question 98
  • Question 99
  • Question 100
  • Epilogue
Powered by GitBook
On this page
  • Question
  • Answer

Question 24

Question

How would you implement a Promise-based API client with retries, timeouts, and cancellations?

Answer

Here's a blueprint for implementing a Promise-based API client with retries, timeouts, and cancellations in JavaScript. This example focuses only on the core concepts. This can be adapted to your specific API requirements:

class ApiClient {
  constructor(baseUrl) {
    this.baseUrl = baseUrl; // Your base API URL
  }

  async request(method, path, data = null, options = {}) {
    const defaultOptions = {
      retries: 3, 
      retryDelay: 1000, // Initial retry delay in milliseconds
      timeout: 5000, // Timeout duration in milliseconds
    };

    options = { ...defaultOptions, ...options }; // Merge defaults with provided options

    return new Promise((resolve, reject) => {
      const controller = new AbortController(); // For cancellation
      let retriesLeft = options.retries;

      const makeRequest = async () => {
        try {
          const response = await fetch(`${this.baseUrl}${path}`, {
            method, 
            headers: { 'Content-Type': 'application/json' }, 
            body: JSON.stringify(data),
            signal: controller.signal, // Pass cancellation signal to fetch
          });

          if (!response.ok) {
            const error = await response.text();
            throw new Error(`API Request Failed: ${error}`); // Handle non-successful responses
          }
          return resolve(await response.json()); 
        } catch (err) {
          if (retriesLeft > 0) {
            console.warn(`Request failed, retrying... (${retriesLeft} attempts left)`);
            retriesLeft--;
            setTimeout(() => makeRequest(), options.retryDelay);
          } else {
            reject(err);
          }
        }
      };

      makeRequest(); // Initiate the first request
    });
  }

  // Example API calls (you'd add more based on your API)
  async getUsers() {
    return this.request('GET', '/users'); 
  }

  async createUser(user) {
    return this.request('POST', '/users', user); 
  }
}


// Usage Example:
const client = new ApiClient('https://api.example.com'); // Your API base URL

client.getUsers()
  .then((data) => console.log(data))
  .catch((error) => console.error('Error:', error)); 

Explanation:

  1. ApiClient Class: Represents the client that interacts with your API. It holds the base URL and provides methods for making requests.

  2. request() Method: The core method to handle all API calls.

    • Takes method, path, data, and options.

    • Merges default retry, timeout, etc., options with any provided by the caller.

    • Uses AbortController for cancellation (more on this later).

  3. Promise Handling:

    • Returns a Promise that resolves with the API response data or rejects with an error.

    • Implements retry logic within a loop using setTimeout. If retries fail, it rejects the promise.

  4. Timeout: Uses fetch's timeout option (signal: controller.signal) to abort requests exceeding the specified time. You can integrate this with your own timeout handling if needed.

  5. Cancellation:

    • The AbortController object allows you to signal cancellation of a request using controller.abort().

  6. Example API Calls (getUsers, createUser): Demonstrates how to use the request() method for different API endpoints.

Key Points and Enhancements:

  • Error Handling: Consider adding more granular error handling, logging, and potential fallback mechanisms within your API client.

  • Rate Limiting: Implement logic to handle rate limiting by the API you're interacting with (e.g., by pausing requests or using exponential backoff).

  • Caching: Implement a simple caching mechanism for frequently accessed data to improve performance.

PreviousQuestion 23NextQuestion 25

Last updated 9 months ago