Skip to main content

Featured

🏁 Day 30 — Final Project: JavaScript Portfolio App

🏁 Day 30 — Final Project: JavaScript Portfolio App Hey Guys Congratulations! You’ve reached Day 30 — the final step of the JavaScript Advanced Course. Keep Learning Today, you will build a complete, interactive Portfolio Web Application using pure JavaScript, DOM manipulation, LocalStorage, and responsive UI techniques. This project showcases all your skills and is perfect for your resume, GitHub, and job applications. 🎯 1. What We Are Building This final project is a fully interactive portfolio website built using HTML, CSS, and JavaScript only — no frameworks. Your portfolio will include: Navbar with smooth scrolling Animated hero section Projects section with filters Skills section with dynamic bars Contact form (with LocalStorage backup) Dark/Light theme switcher Scroll reveal animations Responsive layout for mobile & desktop This project demonstrates mastery of front-end fundamentals and modern JavaScript practices. 📁 2. Fold...

⚠️ Day 23 — Error Handling & Try...Catch

⚠️ Day 23 — Error Handling & Try...Catch

Hey Guys Errors happen — network failures, bad data, and unforeseen edge cases. Today we’ll learn robust patterns to catch, classify, and recover from errors in JavaScript, both in synchronous code and in asynchronous flows. This makes your apps resilient and your users happier.


🔎 Why error handling matters

When something fails in production, it should fail gracefully. If an app throws an uncaught error, the UI may break, data may be lost, or security issues may surface. Proper error handling helps you:

  • Provide clear, actionable messages to users.
  • Log errors for debugging and monitoring (Sentry, LogRocket, server logs).
  • Retry or fallback when appropriate (retry network calls, show cached data).
  • Prevent cascading failures across app components.

⚙ Basic try / catch / finally

The `try` block contains code that may throw. The `catch` block handles the error. The `finally` block runs regardless — ideal for cleanup tasks.

try {
  const data = JSON.parse(someString);
  // use data
} catch (err) {
  console.error('Parsing failed:', err.message);
  // show friendly UI message
} finally {
  // cleanup, remove loading indicators
}
  

🧩 Throwing custom errors

Throw meaningful errors with names/types to let higher-level code decide how to handle them.

class ValidationError extends Error {
  constructor(message, field) {
    super(message);
    this.name = 'ValidationError';
    this.field = field;
  }
}

function validateUser(user) {
  if (!user.email) throw new ValidationError('Email required', 'email');
}
  

Catchers can then use `instanceof` or `err.name` to implement targeted recovery.

📡 Handling fetch() and network errors

`fetch` does not reject on HTTP error status — it only rejects on network failure. Always check `response.ok` and throw accordingly.

async function safeFetch(url) {
  try {
    const res = await fetch(url);
    if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`);
    const data = await res.json();
    return { ok: true, data };
  } catch (err) {
    return { ok: false, error: err };
  }
}

const result = await safeFetch('/api/data');
if (!result.ok) {
  // show fallback UI, log error
}
  

🔁 Retry strategies

For transient network issues, retrying with backoff often fixes the problem. Use exponential backoff to avoid hammering the server.

async function retry(fn, attempts = 3, delay = 500) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (err) {
      if (i === attempts - 1) throw err;
      await new Promise(r => setTimeout(r, delay * Math.pow(2, i)));
    }
  }
}
  

Use this for non-idempotent operations only when safe or for GET requests where retrying is fine.

🛡 Security & error messages

  • Show friendly messages to users — do not expose raw stack traces.
  • Log detailed errors to a secure backend or third-party monitoring tool.
  • Avoid including sensitive data in error messages (tokens, PII).

📦 Centralized error handling patterns

Create a small error handler module that decides whether an error is recoverable, how to present it, and whether to send it to telemetry.

function handleError(err, context = {}) {
  // classify error
  if (err instanceof ValidationError) {
    showFieldError(err.field, err.message);
    return;
  }
  // network error
  if (err.message && err.message.startsWith('HTTP')) {
    showToast('Network problem. Please try again.');
  }
  // log detailed info to server
  sendErrorToServer({err, context});
}
  

🧠 Async error handling – best practices

  1. Prefer `try/catch` inside `async` functions to handle errors locally when you can recover.
  2. Use a safe wrapper pattern to avoid repetitive try/catch blocks:
const to = p => p.then(v => [null, v]).catch(e => [e, null]);

// usage:
const [err, data] = await to(fetch('/api').then(r => r.json()));
if (err) handleError(err);
  

🧪 Testing error paths

Unit tests should simulate failures to verify recovery flows. Use mock fetches, thrown errors, and network timeouts in tests.

📈 Observability — logging & monitoring

Send errors to a logging service with context — user id, route, recent actions. Monitoring helps detect spikes and regressions quickly.

⚠️ Common pitfalls & how to avoid them

  • Swallowing errors silently — always log or report them.
  • Showing raw errors to users — sanitize messages.
  • Retrying non-idempotent operations carelessly — consider side effects.
  • Mixing UI errors and program state — keep concerns separate.

📝 Practice tasks (realistic)

  1. Wrap a third-party fetch in a `safeFetch` and implement retry+backoff.
  2. Create a `ValidationError` and ensure forms display field-level messages when thrown.
  3. Simulate network timeouts and confirm your UI shows cached content or a retry button.

🎯 Summary

Error handling is not optional — it’s a feature. By classifying errors, providing graceful fallbacks, logging to observability tools, and using retry strategies carefully, you make apps reliable and maintainable. Practice these patterns today to build production-grade front-end systems.

Comments