این هم ترجمه بخش بسیار مهم و کاربردی مدیریت خطاها و استثناها (Exception handling) به زبان کاملاً ساده، روان و خودمونی برای سایتت:
در دنیای برنامهنویسی، خطاها همیشه اتفاق میافتند. جاوااسکریپت بهت این قدرت رو میده که با استفاده از دستور throw خطاها رو خودت عمداً پرتاب کنی (ایجاد کنی) و با استفاده از دستور try...catch اونها رو هوا بزنی و مدیریت کنی تا برنامهات کرش نکنه و خراب نشه.
توی جاوااسکریپت تقریباً هر چیزی رو (مثل یک عدد یا متن ساده) میتونی به عنوان خطا پرتاب کنی. اما این کار زیاد حرفهای نیست! بهتره به جای متن ساده، از اشیاء خطای استانداردی که خود جاوااسکریپت برای این کار ساخته استفاده کنی:
خطاهای اکمااسکریپت (ECMAScript exceptions): مثل ساختار استاندارد new Error().
خطاهای مرورگر (DOMException): خطاهایی که مربوط به محیط وب و مرورگر میشن.
throw)هر زمان که در کدت به یک وضعیت غیرمجاز رسیدی، با دستور throw میتونی یک خطا صادر کنی:
throw عبارت_مورد_نظر;
همانطور که گفتم، نوع این عبارت فرقی نمیکنه؛ میتونی هر چیزی بگذاری:
throw "خطای شماره ۲"; // یک متن ساده
throw 42; // یک عدد
throw true; // یک مقدار بولین
throw {
toString() {
return "من یک شیء خطا هستم!";
}
};
try...catch)این دستور مثل یک توری نجات عمل میکنه. کدهایی رو که نگران هستی خراب بشن، میگذاری داخل بلاک try (به معنی امتحان کردن). اگر همه چیز خوب پیش بره که هیچ؛ اما اگر کوچکترین خطایی رخ بده، جاوااسکریپت فوراً کد رو متوقف میکنه و کنترل رو میسپاره به بلاک catch (به معنی گرفتن خطا) تا اونجا مشکل رو حل کنی.
علاوه بر اینها، یک بخش اختیاری به اسم finally هم داریم. کدهای داخل finally در هر صورت (چه کدت خطا بده و چه بدون خطا اجرا بشه) آخرِ کار اجرا میشن.
فرض کن تابعی داری که عدد ماه (۱ تا ۱۲) رو میگیره و اسمش رو برمیگردونه. اگر کاربر عددی خارج از این بازه بده، تابع یک خطا پرتاب میکنه:
function getMonthName(mo) {
mo--; // کم کردن یک واحد برای هماهنگی با ایندکس آرایه (صفر = ژانویه)
const months = [
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
];
if (!months[mo]) {
// اگر ماه وجود نداشت، اینجا خطا پرتاب میکنیم:
throw new Error("کد ماه وارد شده غیراستاندارد است!");
}
return months[mo];
}
try {
// کدی که میخوایم امتحانش کنیم:
monthName = getMonthName(myMonth);
} catch (e) {
// اگر خطایی رخ داد، این بخش اجرا میشه:
monthName = "نامشخص";
console.error(e); // پیام خطا رو برای بررسی به سیستم گزارش میدیم
}
catchبلاک کچ یک ورودی (توی پرانتز) میگیره که همان شیء خطای پرتاب شده است. این متغیر فقط و فقط داخل آکلوادهای catch زنده است و بعد از اون از بین میره:
try {
throw "یک خطای فرضی";
} catch (err) {
// متغیر err حاوی متن "یک خطای فرضی" است
console.error(err);
}
یک فوت کنکوری: موقع چاپ کردن خطاها توی بلاک catch، همیشه به جای
console.logازconsole.errorاستفاده کن. این کار باعث میشه پیام توی مرورگر با رنگ قرمز و فرمت رسمی خطا چاپ بشه که پیدا کردنش برای خودت خیلی راحتتره.
finallyهمانطور که گفتیم، کدهای finally همیشه اجرا میشن. این بخش برای کارهای پاکسازی و بستن منابعی که باز موندن فوقالعاده است. مثلاً اگر فایلی رو باز کردی و وسط کار باهاش خطایی رخ داد، با finally مطمئن میشی که فایل در هر صورت بسته میشه و باز نمیمونه:
openMyFile(); // باز کردن فایل
try {
writeMyFile(theData); // نوشتن اطلاعات در فایل (که ممکنه خطا بده)
} catch (e) {
handleError(e); // مدیریت خطا
} finally {
closeMyFile(); // خیالمون راحته که فایل در هر شرایطی بسته میشه
}
finally زرنگی میکنه!اگر داخل بلاک try یا catch دستورِ بازگشت یا همان return نوشته باشی، جاوااسکریپت اون رو موقتاً نگه میداره تا اول بلاک finally اجرا بشه. حالا اگر خودِ finally هم دستور return داشته باشه، مقدارِ قبلی رو کلاً پاک میکنه و مقدار خودش رو برمیگردونه!
به این کد عجیب نگاه کن:
function f() {
try {
console.log(0);
throw "یک خطای الکی";
} catch (e) {
console.log(1);
return true; // این ریترن موقتاً معلق میمونه...
} finally {
console.log(3);
return false; // این ریترن میاد روی قبلی و مقدار خروجی تابع رو false میکنه!
}
}
console.log(f()); // خروجی به ترتیب: 0 و 1 و 3 و در نهایت false
این اووررایت کردن (رو نویسی) حتی برای خطاهایی که دوباره پرتاب میشن هم اتفاق میافته؛ یعنی اگر در finally دستور return بگذاری، خطایی که بالا پرتاب شده بود کلاً خفه میشه و نادیده گرفته میشه!
تو میتونی چندتا دستور try...catch رو داخل همدیگه بنویسی. اگر یک بلاک try داخلی، بخش catch نداشته باشه، حتماً باید بخش finally داشته باشه. در این صورت اگر خطایی توی بخش داخلی رخ بده، چون خودش کچ نداره، خطای پرتاب شده میره سراغ بخش catch لایه بیرونیتر تا اونجا گرفته بشه.
وقتی از ساختار رسمی new Error("پیام خطا") استفاده میکنی، این شیء دو تا ویژگی (Property) خیلی مهم بهت میده:
name: نوع و کلاس خطا رو مشخص میکنه (مثلاً سیستم میگه این یک 'Error' هست یا 'DOMException').
message: همان پیام متنی و خلاصهای هست که خودت موقع ساختن خطا نوشتی.
استفاده از این ساختار بهت کمک میکنه که توی بلاک کچ، خطاهای دستساز خودت رو از خطاهای خودِ سیستم جاوااسکریپت تفکیک کنی:
function doSomethingErrorProne() {
if (کد ما دچار اشتباه شد) {
throw new Error("دیتابیس قطع شده است!");
}
}
try {
doSomethingErrorProne();
} catch (e) {
console.error(e.name); // خروجی: 'Error'
console.error(e.message); // خروجی: 'دیتابیس قطع شده است!'
}
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://developer.mozilla.org/en-US/docs/Web/JavaScript