DEV Community

Cover image for Efficient Retries: Implementing Fibonacci Backoff in JavaScript Fetch Requests
Huynh Thanh Phuc
Huynh Thanh Phuc

Posted on

Efficient Retries: Implementing Fibonacci Backoff in JavaScript Fetch Requests

Introduction:

In the world of web development, handling network requests is a common task. However, network hiccups, server issues, or other transient problems can lead to failed requests. To enhance the robustness of your application, implementing a retry mechanism is crucial. In this blog post, we'll explore an interesting approach called Fibonacci Backoff and learn how to implement it in JavaScript fetch requests.

Understanding the Need for Retry Mechanisms

Network requests are inherently unpredictable. Various factors such as server load, network congestion, or temporary outages can cause requests to fail. To ensure a smooth user experience, it's essential to handle these failures gracefully. This is where retry mechanisms come into play.

The Concept of Fibonacci Backoff

Fibonacci Backoff is a retry strategy that introduces increasing wait times between successive retries. The wait times are determined by the Fibonacci sequence, where each subsequent value is the sum of the two preceding ones. This approach prevents overwhelming the server with rapid, repeated requests while providing a gradually increasing backoff period.

The TypeScript Implementation

Let's delve into a practical implementation of Fibonacci Backoff in TS, specifically in the context of fetch requests. The code snippet provided demonstrates a reusable function, fetchDataWithFibonacciBackoff, designed to fetch data from a given URL with retry capabilities.

export default async function fetchDataWithFibonacciBackoff(
    url: string,
    init?: RequestInit,
    { tries } = { tries: 6 },
): Promise<Response> {
    let controller: AbortController;
    let attempt = 0;
    let fib = [1, 2];

    while (attempt <= tries) {
        try {
            controller = new AbortController();
            const signal = controller.signal;

            const response = await fetch(url, { ...init, signal: signal });
            if (response.ok) {
                return response;
            } else {
                throw new Error(`Request failed with status: ${response.status}`);
            }
        } catch (e) {
            if (attempt === tries) {
                controller.abort();
                throw e; // If it's the last attempt, re-throw the error
            } else {
                const waitTime = fib[attempt];
                console.log(`Attempt ${attempt + 1}/${tries + 1} failed. Retrying in ${waitTime} seconds.`);
                console.error(e);
                await new Promise(resolve => setTimeout(resolve, waitTime * 1000)); // Wait for the specified time
                attempt++;

                // Generate the next Fibonacci number
                fib.push(fib[fib.length - 1] + fib[fib.length - 2]);
            }
        }
    }

    controller.abort();
    throw new Error(`All ${tries + 1} attempts failed.`);
}


Enter fullscreen mode Exit fullscreen mode

Conclusion

Implementing retry mechanisms is a crucial aspect of building robust and resilient applications. The Fibonacci Backoff strategy provides an elegant solution, introducing a balance between responsiveness and avoiding overwhelming server resources. By incorporating this approach into your fetch requests, you can enhance the reliability of your web applications in the face of transient network issues.

Buy Me a Coffee:
Buy Me A Coffee

Top comments (0)