9. الأخطاء والاستثناءات

لا يمتلك جافا سكريبت نظام استثناءات متطورًا للغاية. ومع ذلك، فإنه يوفر الأمر [throw] الذي يسمح بالإبلاغ عن خطأ، بالإضافة إلى بنية try / catch / finally التي تسمح باعتراض هذه الأخطاء.
9.1. نص برمجي [excep-01]
في البرنامج النصي التالي، سنعرض التاريخ الحالي بالشكل [heures:minutes:secondes:millisecondes]. للقيام بذلك، سنستخدم مكتبة jS تسمى [moment.js]. نقوم بتثبيتها، كالمعتاد، باستخدام أداة [npm]:

رمز البرنامج النصي هو التالي:
'استخدم الصارم؛
// حزمة moment
import moment from 'moment';
...
لمعرفة كيفية كتابة السطر [import] في السطر 4، يمكننا الاطلاع على تعريف الوحدة النمطية [moment]:

- في [1-2]، ننتقل إلى تعريف الوحدة النمطية؛
- في [3]، لدينا ملف Typescript، وليس Javascript. عند التنفيذ، يتم ترجمة ملف Typescript هذا إلى ملف Javascript قبل استخدامه؛
- في [4]، نبحث عن التعليمات [export] (Ctrl-F)؛
- في [5]، تقوم التعليمات بتصدير الكائن [moment]. يمكن استيراد هذا الكائن إلى ES6 بالطريقة التالية:
import moment from 'moment';
يمكن استخدام أي اسم لاستيراد الكائن [moment]، على سبيل المثال:
import m from 'moment';
لنعد إلى كود البرنامج النصي:
'use strict';
// حزمة moment
import moment from 'moment';
// مبدأ try / catch / finally
for (let i = 0; i < 10; i++) {
// التاريخ - الوقت الحالي
const now = Date.now();
// تنسيق الوقت للحصول على الميلي ثانية
const time = moment(now).format("HH:mm:ss:SSS");
// الميلي ثانية
const milli = Number(time.substr(time.length - 3));
// العرض
console.log("--------------------itération n° ", i, "à", time);
try {
// عدد متغير حسب الوقت الحالي
const nbre = milli % 2;
if (nbre === 0) {
// إرسال رسالة خطأ
throw "erreur";
}
// إذا وصلنا إلى هنا، فهذا يعني أنه لم تحدث أي أخطاء
console.log("pas d'erreur");
} catch (error) {
// إذا وصلنا إلى هنا، فهذا يعني أن هناك خطأ
console.log("erreur1=", error);
} finally {
// يتم تنفيذه في جميع الحالات سواء حدث خطأ أم لا
console.log("finally")
}
}
تعليقات
- السطر 4: استيراد مكتبة [moment]؛
- مبدأ البرنامج النصي هو تكرار الدورة 10 مرات (السطر 7). في كل دورة، يتم استرداد الوقت الحالي في شكل [heures:minutes:secondes:millisecondes] (الأسطر 8-13)؛
- إذا كان عدد المللي ثانية زوجيًا، يتم إرسال رسالة خطأ (الأسطر 19-22)؛
- الهدف هنا هو فهم كيفية عمل try / catch / finally
التنفيذ
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-01.js"
--------------------itération n° 0 à 17:57:04:440
erreur1= erreur
finally
--------------------itération n° 1 à 17:57:04:447
pas d'erreur
finally
--------------------itération n° 2 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 3 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 4 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 5 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 6 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 7 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 8 à 17:57:04:449
pas d'erreur
finally
--------------------itération n° 9 à 17:57:04:449
pas d'erreur
finally
نلاحظ أن الجملة [finally] يتم تنفيذها دائمًا سواء كان هناك خطأ أم لا.
9.2. نص برمجي [excep-02]
يمكن لهذا البرنامج النصي الذي تطلقه التعليمات [throw] تشغيل أي نوع من البيانات، ويتم استرداد هذه البيانات بالكامل بواسطة الجملة [catch].
'use strict';
// يمكننا "إلقاء" (throw) أي شيء تقريبًا للإبلاغ عن خطأ
let i = 0;
console.log("--------------------essai n° ", i);
// إلقاء سلسلة أحرف
try {
throw "msg d'erreur";
} catch (error) {
// حدث خطأ
console.log("erreur=[", error, "], type=", typeof (error));
}
// إنشاء جدول
i++;
console.log("--------------------essai n° ", i);
try {
throw [1, 2, 3]
} catch (error) {
// حدث خطأ
console.log("erreur=[", error, "], type=", typeof (error));
}
// تشغيل كائن حرفي
i++;
console.log("--------------------essai n° ", i);
try {
throw { nom: "hercule", pays: "grèce antique" }
} catch (error) {
// حدث خطأ
console.log("erreur=[", error, "], type=", typeof (error));
}
// إطلاق نوع Error
i++;
console.log("--------------------essai n° ", i);
try {
throw new Error("erreur de connexion au réseau");
} catch (error) {
// حدث خطأ
console.log("erreur=[", error, "], type=", typeof (error));
}
// إثارة نوع Error
i++;
console.log("--------------------essai n° ", i);
try {
throw new Error("erreur de connexion au réseau");
} catch (error) {
// حدث خطأ - الرسالة موجودة في [error.message]
console.log("erreur.message=[", error.message, "], type(error)=", typeof (error));
}
تعليقات
- السطران 35 و44: [Error] هي فئة جافا سكريبت يقبل منشئها رسالة خطأ كمعلمة اختيارية أولى. يمكن استرداد هذه الرسالة في الخاصية [Error.message] (السطر 47)؛
- هناك فئات أخرى غير [Error] للإبلاغ عن خطأ: [EvalError، InternalError، RangeError، ReferenceError، SyntaxError، TypeError، URIError)؛
التنفيذ
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-02.js"
--------------------essai n° 0
erreur=[ msg d'erreur ], type= string
--------------------essai n° 1
erreur=[ [ 1, 2, 3 ] ], type= object
--------------------essai n° 2
erreur=[ { nom: 'hercule', pays: 'grèce antique' } ], type= object
--------------------essai n° 3
erreur=[ Error: erreur de connexion au réseau
at Object.<anonymous> (c:\Data\st-2019\dev\es6\javascript\exceptions\excep-02.js:35:9)
at Object.<anonymous> (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:251206)
at c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:245054
at Generator.next (<anonymous>)
at bl (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:245412)
at kl (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:247659)
at Object.u (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:287740)
at Object.o (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:287137)
at Object.<anonymous> (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:284879)
at Object.apply (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:199341) ], type= object
--------------------essai n° 4
erreur.message=[ erreur de connexion au réseau ], type(error)= object
9.3. نص برمجي [excep-03]
يُظهر هذا البرنامج النصي أنه يمكن، في [catch]، التمييز بين نوع المثيل [Error] الذي اعترضه [catch]:
'use strict';
// حزمة moment
import moment from 'moment';
// تمييز مثيل Error المستلم في [catch]
for (let i = 0; i < 10; i++) {
// التاريخ - الوقت الحالي
const now = Date.now();
// تنسيق الوقت للحصول على الميلي ثانية
const time = moment(now).format("HH:mm:ss:SSS");
// الميلي ثانية
const milli = Number(time.substr(time.length - 3));
console.log("--------------------itération n° ", i);
try {
// العدد [0, 1, 2]
const nbre = milli % 3;
switch (nbre) {
case 0:
throw new ReferenceError("erreur 1");
case 1:
throw new RangeError("erreur 2");
default:
throw new EvalError("erreur 3");
}
} catch (error) {
// حدث خطأ
if (error instanceof ReferenceError) {
console.log("ReferenceError :", error.message);
} else {
if (error instanceof RangeError) {
console.log("RangeError :", error.message);
}
else {
if (error instanceof EvalError) {
console.log("EvalError :", error.message);
}
}
}
}
}
التنفيذ
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-03.js"
--------------------itération n° 0
ReferenceError : erreur 1
--------------------itération n° 1
RangeError : erreur 2
--------------------itération n° 2
RangeError : erreur 2
--------------------itération n° 3
RangeError : erreur 2
--------------------itération n° 4
RangeError : erreur 2
--------------------itération n° 5
RangeError : erreur 2
--------------------itération n° 6
EvalError : erreur 3
--------------------itération n° 7
EvalError : erreur 3
--------------------itération n° 8
EvalError : erreur 3
--------------------itération n° 9
EvalError : erreur 3