Lesson 19 / الدرس 19

Handling errors / معالجة الأخطاء

What try can and cannot catch, why an empty catch is worse than no catch at all, and how to fail in a way that tells the user something true.

ما يستطيع try التقاطه وما لا يستطيع، ولماذا catch فارغة أسوأ من لا التقاط أصلًا، وكيف تخفق على نحو يقول للمستخدم شيئًا صحيحًا.

The shape, and its edges

try {
  risky();
} catch (err) {
  console.error(err);            err.message, err.name, err.stack
} finally {
  cleanUp();                     runs either way
}

throw new Error('Order not found');    always an Error, never a string

try { await load(); } catch (err) { }  await inside try: caught
setTimeout(risky, 0);                  NOT caught by any try around it
The last line is the edge that surprises people. A try catches what happens while it runs, and a callback scheduled for later runs long after the try block has finished. Press the four buttons and watch which failures the handler sees.

Failing usefully

Instead ofDo
catch (e) { }Handle it, or let it through — never silence it
throw "not found"throw new Error("not found") — a string has no stack
alert(err.message)Show the user what to do next, log the detail
try around everythingtry around the one call that can fail
catch (e) { console.log(e) }Also tell the person looking at the screen

The third row is the one that separates a finished feature from an unfinished one. err.message is written for you, not for the user: "NetworkError when attempting to fetch resource" tells them nothing they can act on. "We could not reach the server — check your connection and try again" does, and the technical message still belongs in the console where you will look for it.

Two habits that go with this. Throw Error objects rather than strings: an Error carries a stack trace saying where it came from, and a string carries nothing, so the debugging starts with a search for the text. And keep the try narrow — wrapping fifty lines means the catch cannot know which of them failed, and it will happily catch a typo in your own rendering code and report it to the user as a network problem.

Try it live / جرّب بنفسك

Preview / المعاينة

Check yourself / اختبر نفسك

1. Why does a try around setTimeout(risky, 0) not catch the failure?

2. What is wrong with an empty catch?

3. What should the user see when a request fails?

Your task / مهمتك

Build four buttons, each producing a different failure: a plain throw, a rejected await, a throw inside a timer, and one swallowed by an empty catch. For each, print whether your handler saw it and what the page ended up showing. Then take the swallowed case and fix it properly: catch it, log the technical detail, and put a sentence on the screen that tells a non-technical person what to do next.

ابنِ أربعة أزرار، ينتج كل منها إخفاقًا مختلفًا: رمية صرفة، وawait مرفوضة، ورمية داخل مؤقت، وواحدة تبتلعها catch فارغة. واطبع لكل واحدة هل رآها معالجك وما الذي انتهت الصفحة إلى عرضه. ثم خذ الحالة المبتلعة وأصلحها كما ينبغي: التقطها، وسجّل التفصيل التقني، وضع على الشاشة جملة تقول لغير التقني ما يفعله بعد ذلك.

  • Four different failures, each reported أربعة إخفاقات مختلفة كل منها مُبلَّغ عنه
  • The timer case shown escaping the try حالة المؤقت معروضة وهي تفلت من try
  • The swallowed case shows a wrong value with no message الحالة المبتلعة تُظهر قيمة خاطئة بلا رسالة
  • It is then fixed with a message a user could act on ثم مُصلَحة برسالة يستطيع المستخدم التصرف عليها
How do you want to submit? / كيف تريد التسليم؟