معالجة متقدمة للأخطاء في JavaScript: من try/catch إلى المعترضات العامة
\n\nمعالجة الأخطاء ليست مجرد "تغليف الكود في try/catch". في تطبيقات الإنتاج الحقيقية على Node.js، الإدارة الصحيحة للاستثناءات تسمح بتجنب انهيار الخادم، وتسجيل المشكلات بشكل صحيح، وإعطاء المستخدم رسائل مفهومة. في هذه المقالة، سنشرح التقنيات المتقدمة لمعالجة الأخطاء في JavaScript التي تتجاوز بناء الجملة الأساسي.
\n\n1. الغوص العميق في try/catch و finally
\n\nالتركيبة الكلاسيكية try...catch...finally تظل أساس المعالجة المتزامنة. ومع ذلك، على المستوى المتقدم، من المهم فهم الفروق الدقيقة في عملها.
function riskyOperation(value) {\n if (typeof value !== 'number') {\n throw new TypeError('Argument must be a number');\n }\n if (value < 0) {\n throw new RangeError('Value cannot be negative');\n }\n return Math.sqrt(value);\n}\n\ntry {\n const result = riskyOperation(-4);\n console.log('Result:', result);\n} catch (error) {\n if (error instanceof TypeError) {\n console.error('Type Error:', error.message);\n } else if (error instanceof RangeError) {\n console.error('Range Error:', error.message);\n } else {\n console.error('Unknown error:', error);\n }\n} finally {\n console.log('Cleanup: always executed');\n}\n\nالنقاط الرئيسية:
\n- \n
- كتلة
finallyتُنفذ دائمًا، حتى لو كان هناكreturnفيtryأوcatch. \n - استخدم فئات الأخطاء المضمنة (
TypeError،RangeError،SyntaxError) للتحديد الدقيق. \n - لا تعترض الأخطاء التي لا يمكنك معالجتها - اتركها تتصاعد للأعلى. \n
2. فئات الأخطاء المخصصة وتوسيع Error
\n\nللمشاريع الكبيرة، أنواع الأخطاء القياسية غير كافية. إنشاء فئات خاصة بك يسمح بإضافة بيانات وصفية (حالة HTTP، رمز الخطأ، السياق) ويبسط التصفية.
\n\nclass AppError extends Error {\n constructor(message, statusCode, code) {\n super(message);\n this.name = 'AppError';\n this.statusCode = statusCode;\n this.code = code;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nclass ValidationError extends AppError {\n constructor(message, field) {\n super(message, 400, 'VALIDATION_ERROR');\n this.field = field;\n }\n}\n\nclass DatabaseError extends AppError {\n constructor(message, query) {\n super(message, 500, 'DB_ERROR');\n this.query = query;\n }\n}\n\n// الاستخدام\ntry {\n throw new ValidationError('Email is required', 'email');\n} catch (error) {\n if (error instanceof ValidationError) {\n console.log(`Field: ${error.field}, Status: ${error.statusCode}`);\n }\n}\n\nلماذا هذا مهم: الأخطاء المخصصة تسمح بمعالجة مركزية لسيناريوهات مختلفة (مثلًا في middleware Express.js) وإرجاع JSON منظم للعميل.
\n\n3. معالجة الأخطاء في الكود غير المتزامن: async/await و Promise
\n\nفي Node.js، معظم الكود غير متزامن. الأخطاء في Promise و async/await تتطلب نهجًا خاصًا.
3.1. معالجة Promise
\n\nfunction fetchUserData(userId) {\n return new Promise((resolve, reject) => {\n if (userId <= 0) {\n reject(new RangeError('Invalid user ID'));\n }\n // محاكاة طلب لقاعدة البيانات\n setTimeout(() => resolve({ id: userId, name: 'Alice' }), 100);\n });\n}\n\nfetchUserData(-1)\n .then(user => console.log(user))\n .catch(error => {\n console.error('Promise rejected:', error.message);\n })\n .finally(() => console.log('Cleanup after promise'));\n\n3.2. معالجة async/await
\n\nasync function getUserProfile(userId) {\n try {\n const user = await fetchUserData(userId);\n const posts = await fetchUserPosts(user.id