DAILY NEWS

Stay Ahead, Stay Informed – Every Day

Advertisement
Your trycatch sucks – lets fix it


You’re not handling errors. You’re hiding them.

Every app crashes. Every API fails. Every database hiccups at 2am on a Friday.The difference between a good dev and a great one? What happens next.

Let’s roast your error handling β€” then make it legendary.

🀦 Level 0: The “Trust Me Bro” Dev

No try/catch at all. Just vibes.

const data = await fetchUserData(userId);
console.log(data.profile.name); // πŸ’₯ TypeError: Cannot read properties of undefined

Enter fullscreen mode

Exit fullscreen mode

The crime: One bad response nukes the entire app. Users see a white screen. You get a 3am Slack ping.

🐣 Level 1: The Junior β€” “I Googled try/catch”

try {
const data = await fetchUserData(userId);
setUser(data);
} catch (err) {
console.log(err); // πŸ‘ˆ and… that’s it. shipped.
}

Enter fullscreen mode

Exit fullscreen mode

What’s wrong here?

console.log in production helps nobody β€” users still see a broken UI
No distinction between a 404 and a 500 β€” every error is treated the same
The error disappears into the void (or a DevTools tab nobody has open)

err might be null, a string, or an Error object β€” you’re not checking

The mindset: “At least it won’t crash.” β€” Yeah, it just silently breaks instead. Cool.

πŸ“ˆ Level 2: The Mid-Level β€” “I’ve Been Burned Before”

Now we’re thinking. You’ve seen production fires. You have trust issues with APIs. Good.

2a β€” Typed errors, real messages

try {
const data = await fetchUserData(userId);
setUser(data);
} catch (err) {
if (err instanceof NetworkError) {
showToast(“Connection lost. Check your internet.”, “warning”);
} else if (err.status === 404) {
showToast(“User not found.”, “error”);
} else {
showToast(“Something went wrong. We’re on it.”, “error”);
logger.error(“(fetchUserData)”, { userId, err }); // πŸ‘ˆ goes to Sentry/Datadog
}
}

Enter fullscreen mode

Exit fullscreen mode

βœ… Users get useful feedback, not a frozen screenβœ… Engineers get structured logs, not a haystack of console.logs

2b β€” Undo previous operations (the “atomic mindset”)

Imagine you’re updating a user’s profile and their avatar. Step 1 succeeds. Step 2 fails.Congrats β€” your user now has a corrupted half-state.

let previousProfile = null;

try {
previousProfile = await getProfile(userId); // snapshot
await updateProfile(userId, newProfileData); // step 1
await uploadAvatar(userId, newAvatar); // step 2 πŸ’₯ fails here
} catch (err) {
logger.error(“Profile update failed”, { err });

// ↩️ Roll back step 1 since step 2 failed
if (previousProfile) {
await updateProfile(userId, previousProfile);
}

showToast(“Update failed. Your profile has been restored.”, “warning”);
}

Enter fullscreen mode

Exit fullscreen mode

βœ… Users never see broken half-stateβœ… Rollback is explicit, not accidental

2c β€” Wrap it in a clean utility (stop repeating yourself)

Tired of writing try/catch 50 times? Make a helper:

// utils/tryCatch.js
export async function tryCatch(fn, fallback = null) {
try {
const result = await fn();
return (result, null);
} catch (err) {
return (fallback, err);
}
}

// Usage β€” clean, flat, readable
const (user, err) = await tryCatch(() => fetchUserData(userId));

if (err) {
showToast(“Couldn’t load user.”, “error”);
return;
}

setUser(user);

Enter fullscreen mode

Exit fullscreen mode

βœ… No more deeply nested try/catch pyramidsβœ… Forces you to handle the error at call site β€” can’t ignore it

🧠 Level 3: The Senior β€” “I’ve Seen Things”

You don’t just catch errors. You anticipate them. You build systems that heal themselves.

3a β€” Retry queue with exponential backoff

Networks are flaky. Don’t give up on the first failure.

async function fetchWithRetry(fn, { retries = 3, delay = 500 } = {}) {
for (let attempt = 1; attempt retries; attempt++) {
try {
return await fn();
} catch (err) {
const isLast = attempt === retries;
const isRetryable = err.status >= 500 || err instanceof NetworkError;

if (isLast || !isRetryable) throw err; // don’t retry 401s or 404s

const backoff = delay * 2 ** (attempt – 1); // 500ms β†’ 1s β†’ 2s
logger.warn(`Attempt ${attempt} failed. Retrying in ${backoff}ms…`);
await sleep(backoff);
}
}
}

// Usage
const data = await fetchWithRetry(() => fetchUserData(userId));

Enter fullscreen mode

Exit fullscreen mode

βœ… Temporary blips are invisible to usersβœ… Smart: retries server errors, not client errors (no point retrying a 401)

3b β€” Circuit breaker (stop hammering a dead service)

A retry queue is great β€” unless the whole service is down. Then you’re just DDoS-ing a corpse.

class CircuitBreaker {
constructor(threshold = 5, timeout = 30_000) {
this.failures = 0;
this.threshold = threshold;
this.timeout = timeout;
this.state = “CLOSED”; // CLOSED = healthy, OPEN = tripped, HALF_OPEN = testing
this.nextAttempt = Date.now();
}

async call(fn) {
if (this.state === “OPEN”) {
if (Date.now() this.nextAttempt) {
throw new Error(“Circuit open β€” service unavailable”);
}
this.state = “HALF_OPEN”;
}

try {
const result = await fn();
this.reset();
return result;
} catch (err) {
this.recordFailure();
throw err;
}
}

recordFailure() {
this.failures++;
if (this.failures >= this.threshold) {
this.state = “OPEN”;
this.nextAttempt = Date.now() + this.timeout;
logger.error(“πŸ”΄ Circuit breaker TRIPPED”);
}
}

reset() {
this.failures = 0;
this.state = “CLOSED”;
}
}

// Usage
const userServiceBreaker = new CircuitBreaker();
const data = await userServiceBreaker.call(() => fetchUserData(userId));

Enter fullscreen mode

Exit fullscreen mode

βœ… Failing fast is kind β€” users get an error immediately, not after 10s of retryingβœ… Gives the downstream service a breather to recover

3c β€” Structured error classes (errors that mean something)

Stop throwing raw strings or generic Errors. Give your errors context.

class AppError extends Error {
constructor(message, { code, statusCode = 500, context = {}, retryable = false } = {}) {
super(message);
this.name = “AppError”;
this.code = code;
this.statusCode = statusCode;
this.context = context;
this.retryable = retryable;
this.timestamp = new Date().toISOString();
}
}

// Subclass for specificity
class AuthError extends AppError {
constructor(message, context) {
super(message, { code: “AUTH_ERROR”, statusCode: 401, context, retryable: false });
}
}

class ServiceUnavailableError extends AppError {
constructor(service, context) {
super(`${service} is unavailable`, { code: “SERVICE_DOWN”, statusCode: 503, context, retryable: true });
}
}

// Throwing
throw new ServiceUnavailableError(“UserService”, { userId, attempt: 3 });

// Catching
catch (err) {
if (err instanceof AuthError) {
redirectToLogin();
} else if (err instanceof AppError && err.retryable) {
retryQueue.add(err);
} else {
logger.error(err.code, err.context);
showToast(“Unexpected error. Engineers notified.”);
}
}

Enter fullscreen mode

Exit fullscreen mode

βœ… Catch blocks can make decisions, not just log and prayβœ… Every error carries its own context β€” no more guessing what happened

πŸ—ΊοΈ The Full Picture

What you do
Junior
Mid
Senior

Catch errors
βœ…
βœ…
βœ…

Inform the user
❌
βœ…
βœ…

Send to a logger
❌
βœ…
βœ…

Typed/structured errors
❌
⚠️ partial
βœ…

Rollback on failure
❌
βœ…
βœ…

Retry transient errors
❌
❌
βœ…

Circuit breaker
❌
❌
βœ…

Errors are self-describing
❌
❌
βœ…

βœ… The Golden Rules

Never swallow errors silently. A hidden bug is a time bomb.

Always tell the user something. Frozen UI is worse than an error message.

Log with context, not just a message β€” what failed, who triggered it, when.

Not all errors are equal β€” 404 β‰  500 β‰  NetworkError. Handle them differently.

Retryable β‰  always retry β€” client errors (4xx) should fail fast.

Leave the system in a valid state. Roll back or compensate when operations are partial.

Your catch block is business logic β€” treat it that way.

“The mark of a great engineer isn’t writing code that never fails.It’s writing code that fails gracefully.”

Now go fix your try/catches. πŸ› οΈ



Source link

To Level Up Your React Workflow: 3 Essential VS Code Basic Extensions Every Web Developer Needs to Use



If you are a React developer, your productivity is heavily influenced by your tools. While VS Code is powerful out of the box, the right extensions can transform it from a simple text editor into a high-performance IDE tailored for modern web development.

To take your coding experience to the next level, here are three “must-have” VS Code extensions that will save you hours of debugging and boilerplate typing.

1. Tailwind CSS IntelliSense 🎨

Tailwind CSS has become the industry standard for styling modern React applications. However, remembering every single utility class can be a challenge.

Why you need it:

Auto-Suggestions: As you start typing a class name, it provides a dropdown of available Tailwind utilities.

Color Previews: No more guessing what bg-t looks like. A small color swatch appears right in your gutter or next to the code.

Faster Coding: It reduces the need to constantly flip back and forth between your code and the Tailwind documentation.

2. ES7+ React/Redux/React-Native Snippets ⚑

Stop writing export default function… manually every single time you create a new file. This extension is a massive time-saver for repetitive React patterns.

The Power Move:After installing this, you can simply type a short command like rafce (React Arrow Function Component Export) and hit Enter.

Result: It instantly generates a full, boilerplate-ready React component with imports and exports included. Whether you are working on hooks, Redux, or React Native, these snippets make your development cycle significantly faster.

3. ESLint πŸ”

Writing code is easy; maintaining clean, bug-free code is the hard part. ESLint is your first line of defense against “silly” mistakes that break your build.

Why you need it:

Error Detection: It highlights potential bugs and syntax errors in real-time with red underlines before you even save the file.

Clean Code Standards: It enforces consistent coding styles across your project, ensuring your code remains professional and readable.

Auto-Fixing: Many common linting errors can be fixed automatically on save, keeping your focus on logic rather than formatting.

Final Thoughts πŸ’‘

By integrating Tailwind CSS IntelliSense, ES7+ Snippets, and ESLint into your VS Code setup, you aren’t just codingβ€”you’re coding smarter. These tools eliminate friction, reduce errors, and allow you to focus on building amazing user experiences.

What’s your favorite VS Code extension for React? Let me know in the comments below! πŸ‘‡



Source link