I’ll be real: when I first started coding, error handling was an afterthought. Errors? They were just “part of the journey,” right? But, after a few too many mystery bugs and app crashes, I finally decided to tackle error handling properly. Maybe these tips will save someone else some headaches,
......or maybe I’m just here documenting my own mess. Let’s dive in!
Early Days: Playing Whack-a-Mole with Errors 🐹
At first, my error-handling strategy was more “throw in a console.log()
and hope for the best.” But as projects grew, this approach crashed and burned—literally. 💥 My app would keep breaking, and I was left guessing why. Lesson learned? Errors don’t just “disappear” Ignoring them only makes them come back stronger. 😅
Learning to Respect the try-catch
🔍
Eventually, I realized try-catch
blocks could actually be lifesavers. By wrapping code in try-catch
, I could see where errors happened and even fix them. Here’s what that looked like:
try {
const data = await fetchData();
} catch (error) {
console.error("An error happened:", error);
}
It made debugging a lot easier! But catching errors was just the beginning—I needed to handle them properly. 🤓
Managing Results: Success or Failure? ✅❌
Next, I noticed my functions were returning... unclear results. Was null
a failure? An empty result? Who knows! To avoid confusion, I started returning { success: true }
for success and { success: false, error }
for failures:
const result = await db.insert(data);
if (!result) throw new Error("Insert failed");
return { success: true };
Now, it’s clear whether things went right or wrong. No more head-scratching over ambiguous returns! 🤯
Error Messages in Two Languages? 🌍
One day, I found out I needed error messages in both English and Arabic. Because, you know, why not? 🥲 So I set up a little message map:
const MSGS = {
OTP_FAILED: {
en: "OTP verification failed.",
ar: "فشل التحقق من الرمز."
},
};
It was surprisingly handy! Now I could grab MSGS.OTP_FAILED[locale]
and return the right message in the right language. This little tweak was a game-changer. ✨
Putting It All Together 🧩
Eventually, I got to a setup that actually worked. I used try-catch at a high level, with each function either returning { success: true }
or throwing an error. Here’s what it looked like:
export const otpCreate = async (otp, locale) => {
const row = await db.insert(tableOtp).values(otp).returning();
if (!row || row.length === 0) throw new Error(MSGS.OTP_FAILED[locale]);
return { success: true, data: row };
};
Then, I’d handle it like this:
try {
const result = await otpCreate(otp, locale);
if (result.success) console.log(MSGS.OTP_CREATED[locale], result.data);
} catch (error) {
console.error(MSGS.OTP_FAILED[locale], error.message);
}
Simple, readable, and (finally) consistent. 🙌
Final Thoughts 💡
So, that’s my journey! Here’s what I learned along the way:
- Catch errors close to the source 🕵️ – It makes debugging so much easier.
- Be explicit with success/failure indicators ✅❌ – No more guessing what null means.
- Make error messages clear 🌍 – And if you’re working in multiple languages, a little planning goes a long way.
What about you? Have any other tricks for handling errors and results? I’d love to hear your ideas! And if this saves just one person from a debugging headache, I’ll call it a win. Happy coding! 🎉👩💻👨💻