CodeBlanks Logo Icon CodeBlanks

Retry pattern

Learn the async retry pattern.

Retry pattern

The retry pattern retries an async job if it fails. Example: async function retry(fn, maxAttempts) { for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { return await fn(attempt); } catch (e) { lastError = e; } } throw lastError; }.

Inside try the fn(attempt) call runs. On success the result is returned; on throw catch stores the error and the loop moves on. Up to maxAttempts tries are made; if all fail the last error is thrown. This is the standard way to handle transient network errors: the server might be busy or the connection might drop. The attempt counter increases each try, telling the function which attempt it is on (useful for backoff).

Catching errors with try/catch

The core of the retry pattern is the try/catch block. try { return await fn(attempt); } catch (e) { lastError = e; }. If fn throws the catch catches it and stores it in lastError; the loop continues.

The catch (e) parameter receives the error object. e.message gives the error description. You can log it: console.log("Attempt " + attempt + " failed: " + e.message). This lets you track which attempt failed and why. If all attempts are exhausted throw lastError forwards the last error to the caller. This lets the caller know an error occurred. Retry is only suitable for transient errors; permanent errors (wrong URL) always stay failed.

Practice Write the retry function

Write async function retry(fn, maxAttempts): let lastError; and a for (let attempt = 1; attempt <= maxAttempts; attempt++) loop. In the body try { return await fn(attempt); } catch (e) { lastError = e; console.log("Attempt " + attempt + " failed: " + e.message); }. After the loop throw lastError;. main() is ready.

Starter code

index.js
// Write a retry(fn, maxAttempts) function
// Try with try/catch, retry on failure
// write here

Sample solution

index.js
async function retry(fn, maxAttempts) {
  let lastError;
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await fn(attempt);
    } catch (e) {
      lastError = e;
      console.log("Attempt " + attempt + " failed: " + e.message);
    }
  }
  throw lastError;
}

async function main() {
  let count = 0;
  const fn = async function(attempt) {
    count++;
    if (count < 3) throw new Error("Failed");
    return "Success (attempt " + attempt + ")";
  };
  const result = await retry(fn, 5);
  console.log(result);
}

main();

Expected output

Deneme 1 başarısız: Başarısız
Deneme 2 başarısız: Başarısız
Başarılı (deneme 3)

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What happens if retry(fn, 3) succeeds on the third try?

index.js
await retry(fn, 3)
  • Throws an error
  • Returns the result Correct answer
  • Continues the loop
  • fn is not called

Explanation: If try succeeds the result is returned and the loop ends.

2 Match each piece to its role

Term Meaning
try Attempts the job
catch Catches the error
maxAttempts Attempt limit
throw lastError Throws the last error

3 Complete the catch block

Question
try {
  return await fn(attempt);
} ____ (e) { lastError = e; }
Answer
try {
  return await fn(attempt);
} catch (e) { lastError = e; }

Explanation: Write } catch (e) { ... }.

All lessons in Intermediate