آموزش جاوا اسکریپت – جلسه ۲۰ – مدیریت خطا توسط try و catch

در بخش نوزدهم از سری آموزشی javascript ، ساختارهای نسبتا پیشرفته REST و Spread را یاد گرفتیم. همچنین نحوه کپی کردن یک آبجکت یا آرایه و نیز استفاده از متد arguments جهت دریافت لیست کامل آرگومان های تابع را آموزش دادیم. در این مقاله چگونگی مدیریت خطا یا Error Handling را توسط بلاک Try Catch را یاد خواهیم گرفت.
اهمیتی ندارد شما یک برنامه نویس حرفه ای باشید یا مبتدی، احتمال اینکه در اسکریپت خود دچار خطا شوید بسیار است. بروز خطا ممکن است بخاطر اشتباهات شما بعنوان برنامه نویس باشد، ممکن است بدلیل ورودی های نادرست کاربران باشد، ارسال پاسخ غلط از سمت سرور و غیره باشد.
در حالت پیش فرض اگر اسکریپت شما دچار خطا شود اجرای برنامه متوقف شده و خطای پیش آمده در کنسول مرورگر نمایش می یابد. اما اگر بوسیله try..catch خطاهای احتمالی اسکریپت خود را مدیریت و کنترل کنید، قادر خواهید بود یک خطای کاربر پسند و مناسب به کاربران نمایش دهیم.
دستور try…catch:
ساختار try..catch شامل دو بلاک کد پشت سرهم بصورت زیر می باشد:
try { // code... } catch (err) { // error handling }
تصویر زیر را مشاهده کنید:
ابتدا کدهای داخل بلاک try اجرا می شوند. اگر تمام دستورات این بلاک بدرستی و بدون مشکل اجرا شوند، کدهای داخل بلاک catch نادیده گرفته خواهند شد و اجرا نمی شوند. اما در صورتیکه اجرای بلاک try با خطا مواجه شود وارد بلاک catch خواهیم شد و دستورات داخل این بلاک به ترتیب اجرا می شوند. می توان با تعریف یک آرگومان ورودی مثلا err خطای بوجود آمده را نمایش داد. Catch(err)
بنابراین در صورتیکه اجرای دستورات try با مشکل روبرو شوند کل برنامه متوقف نمی شود و اجرای برنامه مختل نمی شود و می توان این خطا را مدیریت کرد.
در مثال زیر بدلیل تعریف نشدن متغیر lalala دستورات خطوط 1 و 3 اجرا می شوند و دستور 2 هیچوقت اجرا نمی شود:
try { alert('Start of try runs'); // (1) <-- lalala; // error, variable is not defined! alert('End of try (never reached)'); // (2) } catch(err) { alert(`Error has occurred!`); // (3) <-- }
نکته: اگر در داخل ساختار try..catch از توابع زمانبندی مانند setTimeout استفاده کنید، خطای کد مدیریت نمی شود و کدهای داخل catch اجرا نخواهند شد.
مثال:
try { setTimeout(function() { noSuchVariable; // script will die here }, 1000); } catch (e) { alert( "won't work" ); }
با اجرای دستورات فوق در تب console مرورگر، خطای زیر را پس از یک ثانیه (1000 میلی ثانیه) دریافت می کنیم:
Uncaught ReferenceError: noSuchVariable is not defined
به این دلیل که خود تابع یک ثانیه بعد اجرا می شود. زمانیکه اجرای دستورات از ساختار try..catch خارج شده است.
روش صحیح اینست که دستورات مربوط به زمانبندی در اطراف try..catch تعریف شوند. مانند زیر:
setTimeout(function() { try { noSuchVariable; // try..catch handles the error! } catch { alert( "error is caught here!" ); } }, 1000);
محتوایات آبجکت Error در catch:
وقتی خطایی رخ می دهد جاوا اسکریپت یک آبجکت error ایجاد می کند و اطلاعات مربوط به این خطا را در آن ذخیره می کند. سپس این آبجکت به عنوان آرگومان catch تعریف می شود.
try { // ... } catch(err) { // <-- the "error object", could use another word instead of err // ... }
نکته: نام گذاری آرگومان err دلخواه است.
تمام آبجکت های خطا در جاوا اسکریپت بطور پیش فرض دو property دارند:
- name: نام خطا می باشد. بعنوان مثال برای یک متغیر تعریف نشده نام خطا برابر با ReferenceError خواهد بود.
- message: شامل یک پیام متنی در شرح خطا می باشد.
آبجکت Error چند property غیر استاندارد هم دارد که یکی از کاربردی ترین آنها stack می باشد.
stack: یک رشته است که شامل اطلاعات مربوط به مکان بروز خطا در فراخوانی های توابع nested می باشد.
بعنوان مثال:
try { lalala; // error, variable is not defined! } catch(err) { alert(err.name); // ReferenceError alert(err.message); // lalala is not defined alert(err.stack); // ReferenceError: lalala is not defined at (...call stack) // Can also show an error as a whole // The error is converted to string as "name: message" alert(err); // ReferenceError: lalala is not defined }
استفاده از try…catch در یک مثال واقعی:
بیایید ساختار مدیریت خطا توسط try…catch را در یک نمونه کاربردی مشاهده کنیم.
همانطور که می دانیم JSON.parse(str) یک رشته با فرمت json بعنوان ورودی می گیرد و آن را به object تبدیل کرده و بر می گرداند. به مثال زیر دقت کنید:
let json = '{"name":"John", "age": 30}'; // data from the server let user = JSON.parse(json); // convert the text representation to JS object // now user is an object with properties from the string alert( user.name ); // John alert( user.age ); // 30
در این مثال اگر رشته json فرمت نادرستی داشته باشد اجرای برنامه با خطا روبرو می شود و متوقف خواهد شد.
ما بعنوان برنامه نویس جاوا اسکریپت باید بتوانیم خطاهای برنامه را مدیریت کرده و پیغام های مناسب به کاربران نمایش دهیم.
let json = "{ bad json }"; try { let user = JSON.parse(json); // <-- when an error occurs... alert( user.name ); // doesn't work } catch (e) { // ...the execution jumps here alert( "Our apologies, the data has errors, we'll try to request it one more time." ); alert( e.name ); alert( e.message ); }
در بلاک catch مدیریت کرده و name و message خطا را نمایش می دهیم.
عملگر throw در catch:
ابتدا به مثال زیر دقت کنید:
let json = '{ "age": 30 }'; // incomplete data try { let user = JSON.parse(json); // <-- no errors alert( user.name ); // no name! } catch (e) { alert( "doesn't execute" ); }
عملیات parse بدرستی انجام می شود و خطایی ندارد. اما در دستور خط بعد بدلیل عدم وجود name در json ، undefined چاپ می شود و وارد بلاک catch نمی شود. در این گونه موارد باید خودمان یک خطا ایجاد کنیم. توسط دستور throw.
let json = '{ "age": 30 }'; // incomplete data try { let user = JSON.parse(json); // <-- no errors if (!user.name) { throw new SyntaxError("Incomplete data: no name"); // (*) } alert( user.name ); } catch(e) { alert( "JSON Error: " + e.message ); // JSON Error: Incomplete data: no name }
ساختار try..catch..finally
ساختار مدیریت خطای try…catch یک بلاک کد دیگر نیز می تواند داشته باشد بنام finally (تعریف آن اختیاری است).
کدهای داخل بلاک finally همیشه اجرا می شوند. چه کدهای داخل try خطا داشته باشند و چه بدون خطا اجرا شوند.
try { ... try to execute the code ... } catch(e) { ... handle errors ... } finally { ... execute always ... }
بعنوان مثال داریم:
try { alert( 'try' ); if (confirm('Make an error?')) BAD_CODE(); } catch (e) { alert( 'catch' ); } finally { alert( 'finally' ); }
اجرای این مثال ممکن است به دو صورت انجام شود:
- اگر کاربر پاسخ confirm را ok یا yes بدهد کدهای try > catch > finally اجرا می شوند.
- اگر کاربر پاسخ confirm را cancel یا no بدهد کدهای try > finally اجرا می شوند.
در این مقاله، ساختار try, catch را برای مدیریت خطاهای احتمالی در کدهای js، ساختار try-catch-finally و نیز عملگر throw در بلاک catch را فرا گرفتیم. در مقاله بعد یعنی بخش 21 از سری آموزشی جامع js می خواهیم درباره تعریف کلاس و پیاده سازی مفاهیم شی گرایی در زبان جاوا اسکریپت بطور مفصل صحبت کنیم.
دیدگاهتان را بنویسید