مقدمه

مهم نیست چقدر کد خود را با دقت می‌نویسیم، بروز خطا در برنامه‌ها اجتناب‌ناپذیر است. این خطاها می‌توانند ناشی از اشتباهات برنامه‌نویسی (باگ)، ورودی‌های نامعتبر از سوی کاربر، یا مشکلات خارجی مانند قطع شدن ارتباط با سرور باشند. یک اپلیکیشن قوی و کاربرپسند، اپلیکیشنی است که این خطاها را پیش‌بینی کرده و به جای «کرش کردن» یا نمایش یک صفحه سفید، آنها را به شیوه‌ای زیبا و کنترل‌شده مدیریت کند. مدیریت خطا یکی از ستون‌های اصلی ساخت نرم‌افزار قابل اعتماد است.

ساختار try...catch

مکانیزم اصلی جاوااسکریپت برای مدیریت خطاهای زمان اجرا (runtime errors)، دستور try...catch است. این ساختار به ما اجازه می‌دهد تا یک بلوک کد را که ممکن است با خطا مواجه شود، "امتحان" (try) کنیم و در صورت بروز خطا، آن را "بگیریم" (catch) و یک اقدام مناسب انجام دهیم.

بلوک try و catch

کدی که پتانسیل ایجاد خطا را دارد، درون بلوک try قرار می‌گیرد. اگر در حین اجرای این کد خطایی رخ دهد (که به آن پرتاب شدن یک استثنا یا "exception" می‌گویند)، اجرای عادی کد در بلوک try بلافاصله متوقف شده و کنترل برنامه به بلوک catch منتقل می‌شود. بلوک catch یک شیء خطا (error object) به عنوان آرگومان دریافت می‌کند که حاوی اطلاعات مفیدی درباره خطای رخ داده است.

Copy Icon JAVASCRIPT
try {
    console.log('Starting the try block...');
    nonExistentFunction(); // This will cause a ReferenceError
    console.log('This line will not be executed.');
} catch (error) {
    console.error('An error was caught!');
    console.error('Error Name:', error.name);
    console.error('Error Message:', error.message);
}

console.log('Execution continues after the try...catch block.');

در این مثال، چون تابعی به نام nonExistentFunction وجود ندارد، یک ReferenceError پرتاب می‌شود. اجرای بلوک try در همان لحظه متوقف شده و به بلوک catch می‌رود. در آنجا، ما نام و پیام خطا را در کنسول ثبت می‌کنیم. نکته کلیدی این است که برنامه کرش نمی‌کند و اجرای کد بعد از بلوک try...catch ادامه می‌یابد.

بلوک finally

این ساختار می‌تواند یک بلوک اختیاری دیگر به نام finally نیز داشته باشد. کدهای داخل بلوک finally همیشه اجرا می‌شوند، چه در بلوک try خطایی رخ داده باشد و چه رخ نداده باشد. این ویژگی، finally را به مکانی ایده‌آل برای انجام عملیات پاک‌سازی (cleanup) تبدیل می‌کند، مانند بستن یک اتصال شبکه یا آزادسازی منابعی که در بلوک try اشغال شده‌اند.

Copy Icon JAVASCRIPT
try {
    console.log('Opening a resource...');
    // JSON.parse with invalid JSON will throw a SyntaxError
    JSON.parse('{ "malformed": json }');
} catch (error) {
    console.error('Caught a syntax error:', error.message);
} finally {
    console.log('Closing the resource. This runs no matter what.');
}

در این کد، چه خطای JSON.parse رخ دهد یا نه (می‌توانید آن خط را با یک کد بدون خطا جایگزین کنید تا ببینید)، پیام "Closing the resource" همیشه در کنسول چاپ خواهد شد.

شیء Error و دستور throw

شیئی که در بلوک catch دریافت می‌کنیم، معمولاً یک نمونه از شیء داخلی Error یا یکی از فرزندان تخصصی آن است. مهم‌ترین پراپرتی‌های این شیء name (نام خطا، مانند TypeError) و message (توضیح متنی خطا) هستند.

ایجاد خطاهای سفارشی

علاوه بر مدیریت خطاهایی که توسط خود جاوااسکریپت ایجاد می‌شوند، ما می‌توانیم خطاهای سفارشی خودمان را نیز ایجاد و "پرتاب" (throw) کنیم. این کار با استفاده از دستور throw و ساخت یک نمونه جدید از Error انجام می‌شود. این قابلیت به ما اجازه می‌دهد تا خطاهای منطقی مربوط به اپلیکیشن خودمان (مثلاً یک ورودی نامعتبر که از نظر سینتکس جاوااسکریپت مشکلی ندارد) را نیز با همان مکانیزم try...catch مدیریت کنیم.

Copy Icon JAVASCRIPT
function calculateAge(birthYear) {
    if (typeof birthYear !== 'number' || birthYear > new Date().getFullYear()) {
        throw new Error('Invalid birth year provided.');
    }
    return new Date().getFullYear() - birthYear;
}

try {
    const age = calculateAge(2050);
    console.log(age);
} catch (error) {
    console.error('Application Error:', error.message);
}

در این مثال، تابع calculateAge ورودی خود را اعتبارسنجی می‌کند. اگر سال تولد نامعتبر باشد، یک خطای جدید با پیام مشخص `throw` می‌کند. کد فراخواننده این تابع، آن را در یک بلوک try قرار داده تا بتواند این خطای منطقی و سفارشی را گرفته و به شکل مناسبی به کاربر نمایش دهد.

در این درس با مکانیزم‌های اصلی جاوااسکریپت برای مدیریت خطا آشنا شدیم. دانستن نحوه استفاده از try...catch برای جلوگیری از کرش کردن برنامه و دستور throw برای سیگنال دادن خطاهای منطقی، از مهارت‌های ضروری هر برنامه‌نویسی است. اما صرفاً گرفتن خطا کافی نیست؛ باید بدانیم با آن چه کنیم. در درس بعدی، به بررسی الگوها و رویکردهای مختلف برای مدیریت خطاها به شیوه‌ای مؤثر و کاربرپسند خواهیم پرداخت.