۱. چرا خطاهای سفارشی میسازیم؟
«در جاوااسکریپت، ما یک شیء خطای عمومی به نام Error داریم. اما وقتی اپلیکیشن بزرگ میشود، تشخیص اینکه این خطا دقیقاً از کجای سیستم آمده سخت میشود. مثلاً خطای «یافت نشد» میتواند مربوط به کاربر باشد، یا مربوط به منبعی در سرور. برای شفافیت، ما کلاسهای خطای سفارشی میسازیم که از Error ارثبری میکنند.»
۲. نحوه پیادهسازی استاندارد:
«برای ساخت یک خطای سفارشی، یک کلاس جدید تعریف میکنم که آن را با extends Error گسترش میدهم. در تابع constructor، ابتدا پیام خطا را به تابع super پدر میفرستم تا پیام ذخیره شود. سپس نام خطا را روی this.name تنظیم میکنم تا هنگام لاگگیری یا نمایش، قابل تشخیص باشد.»
۳. مشکل پیشفرض (و اهمیت captureStackTrace):
«اینجا یک نکته ظریف وجود دارد: اگر فقط این کار را بکنم، وقتی خطا را در کنسول چاپ کنم، یا در لاگها ببینم، ستونها و شماره خطوط (Stack Trace) به جای اینکه محل واقعی بروز خطا در کد من را نشان دهد، به خط new MyError() درون کلاس اشاره میکند. این موضوع دیباگ کردن را سخت میکند.»
۴. راهحل با V8 (موتور کروم و نود):
«برای رفع این مشکل، در موتور V8 (که در کروم و نود جیاس استفاده میشود) یک متد اختصاصی به نام Error.captureStackTrace وجود دارد. من این متد را درون سازنده کلاسم صدا میزنم و دو آرگومان به آن میدهم: اول، شیء خطای خودم (this) و دوم، خود تابع سازنده (this.constructor).»
«کار این متد این است که حلقهی فراخوانیها را از شیء خطای من حذف میکند. در نتیجه، وقتی ارور رخ میدهد، استکتریس مستقیماً به محلی که کد من آن خطا را پرتاب کرده اشاره میکند و نه به جایای که من خطا را ساختم. این یعنی دیباگینگ بسیار دقیقتر و سریعتر میشود.»
۵. جمعبندی نهایی:
«در نهایت، با این ترفند، خطاهای ما هم نام گویا دارند، هم پیام دقیق، و هم یک استکتریس تمیز که به ما میگوید دقیقاً کجای برنامه مسئله رخ داده است. این کار باعث افزایش کیفیت لاگها و سرعت عیبیابی در تیم میشود.»
اگر مصاحبهکننده از شما کد بخواهد، میتوانید این را نشان دهید:
javascript
class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; // اینجا خطای ساختگی را از استکتریس حذف میکنیم if (Error.captureStackTrace) { Error.captureStackTrace(this, ValidationError); } } } // استفاده: function validateUser(data) { if (!data.name) { throw new ValidationError("نام کاربر الزامی است."); } } try { validateUser({}); // اینجا خطا رخ میدهد } catch (err) { console.log(err.stack); // استکتریس دقیقاً به خط 'throw new ValidationError' اشاره میکند }
اگر سوال شود "چرا فقط super کافی نیست؟" پاسخ دهید: «چون super فقط پیام را ست میکند، اما captureStackTrace به ما امکان میدهد که موقعیت دقیق بروز خطا را در کد حفظ کنیم و ورودیهای اضافی مربوط به خود کلاس خطا را از استک حذف کنیم.»
موفق باشید!