معالجة الأخطاء
مفهوم معالجة الأخطاء
أثناء قيام مفسر الكود بتنفيذ الأوامر فإنه عند حدوث أي خطأ (Error) يتوقف عن تنفيذ الأوامر التالية الموجودة في السكربت و يظهر رسالة الخطأ في الكونسول.
معالجة الأخطاء (Errors Handling) يقصد بها كتابة الكود الذي قد يسبب أي مشكلة بشكل محمي بحيث أنها إذا حدثت فإن ذلك لن يؤدي إلى تعليق السكربت أو إيقاف تنفيذ باقي الأوامر الموجودة فيه.
في هذا الدرس ستتعلم، كيف تحمي الكود من أي أخطاء قد تحدث، كيف تعالج الأخطاء إن وقعت، و كيف تقوم بتعريف أخطاء جديدة.
في صفحات الويب يمكنك رؤية كل الأخطاء و رسائل التحذير التي تحصل على خلف الكواليس بالنقر على الزر F12 و من ثم التوجه للتبويب Console.
أنواع الأخطاء البرمجية
تنقسم الأخطاء البرمجية لثلاث أنواع رئيسية هي:
- أخطاء لغوية ( Syntax Errors ) و التي تحدث عن مخالفة مبادئ اللغة مثل أن يتم تعريف شيء بطريقة خاطئة.
- أخطاء تحدث أثناء التشغيل ( Runtime Errors ) و يقال لها إستثناءات ( Exceptions ) مما يؤدي إلى تعليقه و إيقافه بشكل غير طبيعي.
- أخطاء منطقية ( Logical Errors ) و يقصد منها أن الكود يعمل بدون أي مشاكل و لكن نتيجة تشغيل هذا الكود غير صحيحة.
الأخطاء الغير قابلة للمعالجة
في حال كان الكود يحتوي على أخطاء لغوية ( Syntax Errors ) فيجب إصلاحها كلها قبل تجربة الكود حتى يستطيع مفسر الكود أن ينفذ كل الأوامر الموجودة في السكربت، و إن لم تفعل ذلك فإنه عندما يحاول تنفيذ الأمر المكتوب بشكل خاطئ سيفشل و لن يتابع تنفيذ باقي الأوامر.
لا يمكنك حماية الكود من الأخطاء اللغوية بل يمكنك حمايته من الإستثناءات ( Exceptions ) التي قد تحدث وقت تنفيذ الكود.
الجملتين try و catch
بشكل عام، أي كود قد يسبب تنفيذه خطأ يجب وضعه بداخل حدود الجملة
أي خطأ يحدث في الجملة
try {
// Protected code-a
// هنا نكتب الأوامر التي قد يؤدي تنفيذها إلى حدوث خطأ
}
catch(error) {
// Error Handling code-a
// try هنا نكتب الأوامر التي تعالج الخطأ الذي قد يحدث في الجملة
}
الباراميتر
error.name تعطينا إسم الخطأ الذي حدث.error.message تعطينا رسالة الخطأ الذي حدث، أي الشرح.
إسم الباراميتر
في المثال التالي قمنا بتعريف متغير قيمته عددية، و من ثم حاولنا تحويل قيمته لأحرف كبيرة و عرضها في الصفحة، الأمر الذي سيسبب خطأ.
ملاحظة: عند تجربة الكود فإنه لن يتنفذ و لن يظهر أي نتيجة في الصفحة و لكن لو فتحت الكونسول لظهر لك أنه يوجد خطأ.
المثال الأول
<!DOCTYPE html>
<html>
<body>
<script>
// و قيمته 10 x هنا قمنا بتعريف متغير إسمه
let x = 10;
// لأحرف كبيرة الأمر الذي سيسبب خطأ x هنا حاولنا تحويل قيمة
// للتذكير فإن الخطأ لن يظهر في الصفحة بل يظهر في الكونسول
document.write(x.toUpperCase());
// الأمر التالي لن يتنفذ بسبب الخطأ الذي حصل قبله
document.write('The rest of code will not executed');
</script>
</body>
</html>
الخطأ الذي سيظهر في الكونسول:
سنقوم بإعادة المثال السابق مع وضع الأمر الذي سيسبب مشكلة بداخل جملة
بداخل الجملة
المثال الثاني
<!DOCTYPE html>
<html>
<body>
<script>
// و قيمته 10 x هنا قمنا بتعريف متغير إسمه
let x = 10;
try {
// لأحرف كبيرة الأمر الذي سيسبب خطأ x هنا حاولنا تحويل قيمة
document.write(x.toUpperCase());
}
catch(error) {
// سيتم تنفيذ الأمر التالي try إذا حصل أي خطأ في الكود الموضوع في الجملة
document.write('Failed to convert the value of x.<br>');
}
// الأمر التالي سيتنفذ بشكل طبيعي لأن الخطأ الذي وقع قبله تم معالجته
document.write('The rest of code will be executed');
</script>
</body>
</html>
نتيجة التشغيل:
This rest of code-a will be executed.
سنقوم بإعادة المثال السابق مع طباعة إسم و رسالة الخطأ الذي حدث في الجملة
المثال الثالث
<!DOCTYPE html>
<html>
<body>
<script>
// و قيمته 10 x هنا قمنا بتعريف متغير إسمه
let x = 10;
try {
// لأحرف كبيرة الأمر الذي سيسبب خطأ x هنا حاولنا تحويل قيمة
document.write(x.toUpperCase());
}
catch(error) {
// سيتم طباعة نوع الخطأ و رسالة الخطأ try إذا حصل أي خطأ في الكود الموضوع في الجملة
document.write('Error-type: ' + error.name + '.<br>');
document.write('Error-message: ' + error.message + '.<br>');
}
// الأمر التالي سيتنفذ بشكل طبيعي لأن الخطأ الذي وقع قبله تم معالجته
document.write('The rest of code will be executed.');
</script>
</body>
</html>
نتيجة التشغيل:
Error-message: x.toUpperCase is not a function.
The rest of code-a will be executed.
الجملة finally
الجملة
في حال كان سيتم وضع الجمل الثلاثة معاً فسيكون شكل الكود كما يلي:
try {
// Protected code-a
// هنا نكتب الأوامر التي قد يؤدي تنفيذها إلى حدوث خطأ
}
catch(error) {
// Error Handling code-a
// try هنا نكتب الأوامر التي تعالج الخطأ الذي قد يحدث في الجملة
}
finally {
// Optional Cleanup code-a
// هنا نكتب أوامر ستتنفذ بغض النظر عن ما إن تنفذ الكود بنجاح أو لا
}
عند استخدام الجملة
في المثال التالي لاحظ كيف أنه سيتم تنفيذ الكود الموجود في الجملة
مثال
<!DOCTYPE html>
<html>
<body>
<script>
// و قيمته 10 x هنا قمنا بتعريف متغير إسمه
let x = 10;
try {
// لأحرف كبيرة الأمر الذي سيسبب خطأ x هنا حاولنا تحويل قيمة
document.write(x.toUpperCase());
}
catch(error) {
// سيتم تنفيذ الأمر التالي try إذا حصل أي خطأ في الكود الموضوع في الجملة
document.write('Failed to convert the value of x.<br>');
}
finally {
// أو لم يحصل try الأمر التالي سيتم تنفيذه سواء حصل خطأ في الجملة
document.write('Finally code is executed now.<br>');
}
// الأمر التالي سيتنفذ بشكل طبيعي لأن الخطأ الذي وقع قبله تم معالجته
document.write('The rest of code will be executed.');
</script>
</body>
</html>
نتيجة التشغيل:
Finally code-a is executed now.
The rest of code-a will be executed.
الأمر throw
يمكنك استخدام الأمر
في المثال التالي إذا كانت قيمة المتغير
مثال
<!DOCTYPE html>
<html>
<body>
<script>
// -و قيمته 3 x هنا قمنا بتعريف متغير إسمه
let x = -3;
try {
// لأحرف كبيرة الأمر الذي سيسبب خطأ x هنا حاولنا تحويل قيمة
if (x < 0) {
throw 'x value cannot be negative';
}
else {
document.write('x value is accepted.<br>');
}
}
catch(error) {
// سيتم تنفيذ الأمر التالي try إذا حصل أي خطأ في الكود الموضوع في الجملة
document.write('Error: ' + error + '<br>');
}
// الأمر التالي سيتنفذ بشكل طبيعي لأن الخطأ الذي وقع قبله تم معالجته
document.write('The rest of code will be executed.');
</script>
</body>
</html>
نتيجة التشغيل:
The rest of code-a will be executed.