Course contentsShow
← Node.js
Lesson 190 of 1,9803. Asynchronous Patterns and Flow ControlFree lesson

Implementing Retry Policies

You will build declarative retry logic that handles transient network errors in asynchronous sequences.

Implementing Retry Policies

In this lesson, you will learn how to build declarative retry logic to automatically recover from transient network errors within your asynchronous sequences.

When working with network requests or external APIs, failure is often temporary. Rather than letting a minor "blip" crash your entire process, a retry policy allows your code to pause and try again before ultimately giving up.

Building Declarative Logic

Instead of nesting try/catch blocks inside your business logic, you can encapsulate the retry mechanism into a reusable asynchronous function. This allows you to define how many attempts to make and how long to wait between them.

Here is a simple implementation using a recursive approach to handle transient errors:

async function withRetry(operation, retries = 3, delay = 1000) {
  try {
    return await operation();
  } catch (error) {
    if (retries <= 0) throw error;
    
    console.log(`Failed, retrying in ${delay}ms... (${retries} attempts left)`);
    await new Promise(resolve => setTimeout(resolve, delay));
    
    return withRetry(operation, retries - 1, delay);
  }
}

// Usage:
const fetchData = () => fetch('https://api.example.com/data');
withRetry(fetchData, 3)
  .then(data => console.log("Success!"))
  .catch(err => console.error("Final failure after retries."));

Why this pattern?

By extracting this into a helper function, your core logic remains clean. The withRetry function acts as a wrapper that observes the promise’s state. If the operation fails, it checks the remaining retries count. If attempts remain, it uses setTimeout (wrapped in a Promise) to create a non-blocking delay before invoking the operation again.

This approach is "declarative" because you simply tell your application: "Run this operation, and if it hits a transient wall, handle the retry for me." You aren't manually managing state flags or complex nested loops; you are simply defining a policy that the runtime follows.

Key Takeaway: A declarative retry policy shields your application from transient instability by treating retries as a configurable wrapper around your asynchronous operations.