عندما بدأت العمل مع Express لأول مرة وحاولت معرفة كيفية التعامل مع الأخطاء ، واجهت صعوبة في ذلك. كان هناك شعور بأن لا أحد كتب عن ما أحتاجه. نتيجة لذلك ، كان علي أن أبحث عن إجابات لأسئلتي بنفسي. اليوم أريد أن أقول كل شيء أعرفه عن معالجة الأخطاء في تطبيقات Express. لنبدأ بالأخطاء المتزامنة.

خطأ متزامن معالجة
إذا كنت بحاجة إلى معالجة خطأ متزامن ، فيمكنك أولاً وقبل كل شيء ، استخدام عبارة
throw
،
throw
مثل هذا الخطأ في معالج طلب Express. يرجى ملاحظة أن معالجات الطلب تسمى أيضًا "وحدات التحكم" ، لكنني أفضل استخدام مصطلح "معالج الطلب" كما يبدو لي بمزيد من الوضوح.
إليك ما يبدو عليه:
app.post('/testing', (req, res) => { throw new Error('Something broke! ') })
يمكن اكتشاف مثل هذه الأخطاء باستخدام معالج الأخطاء Express. إذا لم تكن قد كتبت معالج الأخطاء الخاص بك (سنتحدث عن هذا أدناه) ، فسيقوم Express بمعالجة الخطأ باستخدام المعالج الافتراضي.
إليك ما يفعله معالج أخطاء Express القياسي:
- يضبط رمز حالة استجابة HTTP على 500.
- يرسل استجابة نصية إلى الكيان الذي ينفذ الطلب.
- يسجل استجابة نصية إلى وحدة التحكم.
رسالة خطأ المعروضة في وحدة التحكمخطأ غير متزامن معالجة
لمعالجة الأخطاء غير المتزامنة ، تحتاج إلى إرسال خطأ إلى معالج أخطاء Express عبر الوسيطة
next
:
app.post('/testing', async (req, res, next) => { return next(new Error('Something broke again! ')) })
هذا هو ما يحصل على وحدة التحكم عند تسجيل هذا الخطأ.
رسالة خطأ المعروضة في وحدة التحكمإذا كنت تستخدم بنية async / await في تطبيق Express ، فستحتاج إلى استخدام دالة مجمّع مثل أداة
Express-async-handler . يتيح لك هذا كتابة التعليمات البرمجية غير المتزامنة دون كتل
try / catch . اقرأ المزيد عن المزامنة / الانتظار في Express
هنا .
const asyncHandler = require('express-async-handler') app.post('/testing', asyncHandler(async (req, res, next) => {
بعد أن يتم لف معالج الطلب في برنامج
express-async-handler
، يمكنك ، كما هو موضح أعلاه ، إلقاء خطأ باستخدام عبارة
throw
. سينتقل هذا الخطأ إلى معالج أخطاء Express.
app.post('/testing', asyncHandler(async (req, res, next) => { throw new Error('Something broke yet again! ') }))
رسالة خطأ المعروضة في وحدة التحكمكتابة معالج الأخطاء الخاص بك
تأخذ معالجات الأخطاء السريعة 4 وسيطات:
- خطأ
- مسا
- الدقة
- التالي
تحتاج إلى وضعها بعد معالجات متوسطة وطرق.
app.use() app.get() app.post() app.put() app.delete()
إذا قمت بإنشاء معالج الأخطاء الخاص بك ، فسيتوقف Express عن استخدام معالج الأخطاء القياسي. من أجل معالجة الخطأ ، تحتاج إلى إنشاء استجابة لتطبيق الواجهة الأمامية التي تناولت نقطة النهاية التي حدث فيها الخطأ. هذا يعني أنك تحتاج إلى القيام بما يلي:
- قم بإنشاء وإرسال رمز حالة استجابة مناسب.
- شكل وإرسال إجابة مناسبة.
ما رمز الحالة المناسب في كل حالة معينة يعتمد على ما حدث بالضبط. فيما يلي قائمة بالأخطاء الشائعة التي يجب أن تكون مستعدًا للتعامل معها:
- خطأ
400 Bad Request
. المستخدمة في حالتين. أولاً ، عندما لا يقوم المستخدم بتضمين الحقل المطلوب في الطلب (على سبيل المثال ، لم يتم ملء الحقل الذي يحتوي على معلومات بطاقة الائتمان في نموذج الدفع المرسل). ثانياً ، عندما يحتوي الطلب على بيانات غير صحيحة (على سبيل المثال ، إدخال كلمات مرور مختلفة في حقل كلمة المرور وفي حقل تأكيد كلمة المرور). - خطأ
401 Unauthorized
. يتم تطبيق رمز حالة الاستجابة هذا إذا أدخل المستخدم بيانات اعتماد غير صحيحة (مثل اسم المستخدم أو عنوان البريد الإلكتروني أو كلمة المرور). - خطأ
403 Forbidden
. يستخدم عندما لا يُسمح للمستخدم بالوصول إلى نقطة النهاية. - خطأ
404 Not Found
. يتم استخدامه في الحالات التي يتعذر فيها اكتشاف نقطة النهاية. - خطأ
500 Internal Server Error
. يتم تطبيقه عندما يتم إنشاء الطلب المرسلة من الواجهة الأمامية بشكل صحيح ، ولكن حدث بعض الخطأ على الواجهة الخلفية.
بعد تحديد رمز حالة الاستجابة المناسبة ، يجب تعيينه باستخدام
res.status
:
app.use((error, req, res, next) => {
يجب أن يتوافق رمز حالة الاستجابة مع رسالة الخطأ. للقيام بذلك ، أرسل رمز الحالة مع الخطأ.
أسهل طريقة للقيام بذلك هي مع حزمة
الأخطاء http . يسمح بإرسال ثلاثة أجزاء من المعلومات عن طريق الخطأ:
- رمز حالة الاستجابة.
- الرسالة المرتبطة بالخطأ.
- أي بيانات تحتاج إلى إرسالها (هذا اختياري).
إليك كيفية تثبيت حزمة
http-errors
:
npm install http-errors --save
إليك كيفية استخدام هذه الحزمة:
const createError = require('http-errors')
فكر في مثال يتيح لك فهم كل هذا بشكل صحيح.
تخيل أننا نحاول العثور على مستخدم على عنوان بريده الإلكتروني. ولكن لا يمكن العثور على هذا المستخدم. نتيجة لذلك ، قررنا إرسال خطأ
User not found
على
User not found
استجابةً للطلب المقابل ، لإبلاغ المتصل بأنه لم يتم العثور على المستخدم.
إليك ما سنحتاج إلى فعله عند إنشاء الخطأ:
- اضبط رمز حالة الاستجابة على
400 Bad Request
غير صحيح (بعد كل شيء ، أدخل المستخدم بيانات غير صحيحة). ستكون هذه المعلمة الأولى لدينا. - إرسال رسالة إلى المتصل مثل
User not found
. هذه ستكون المعلمة الثانية.
app.put('/testing', asyncHandler(async (req, res) => { const { email } = req.body const user = await User.findOne({ email })
يمكنك الحصول على رمز الحالة باستخدام
error.status
، ورسالة الخطأ باستخدام
error.message
:
نتيجة أخطاء التسجيل في وحدة التحكمثم يتم تعيين حالة الاستجابة باستخدام
res.status
، وتتم كتابة الرسالة إلى
res.json
:
app.use((error, req, res, next) => {
أنا شخصياً أفضل إرسال رمز الحالة والرسالة وتتبع المكدس إلى مثل هذه الاستجابات. هذا يجعل التصحيح أسهل.
app.use((error, req, res, next) => {
status رمز حالة الرد الافتراضي
إذا لم يكن مصدر الخطأ
createError
، فلن يكون له خاصية
status
. فيما يلي مثال تم فيه محاولة قراءة ملف غير موجود باستخدام
fs.readFile
:
const fs = require('fs') const util = require('util')
لن يحتوي كائن الخطأ على خاصية
status
:
app.use((error, req, res, next) => { console.log('Error status: ', error.status) console.log('Message: ', error.message) })
نتيجة خطأ في تسجيل في وحدة التحكمفي مثل هذه الحالات ، يمكنك تعيين رمز الخطأ الافتراضي. وهي نتحدث عن
500 Internal Server Error
:
app.use((error, req, res, next) => { res.status(error.status || 500) res.json({ status: error.status, message: error.message, stack: error.stack }) })
▍ تغيير رمز حالة الخطأ
لنفترض أننا سنقرأ ملفًا معينًا باستخدام البيانات التي قدمها المستخدم. إذا كان هذا الملف غير موجود ، فهذا يعني أننا بحاجة إلى إعطاء خطأ
400 Bad Request
صحيح. بعد كل شيء ، لا يمكن العثور على الخادم لأنه لا يمكن العثور على الملف.
في هذه الحالة ، تحتاج إلى استخدام إنشاء try / catch لالتقاط الخطأ الأصلي. ثم تحتاج إلى إعادة إنشاء كائن خطأ باستخدام
createError
:
app.get('/testing', asyncHandler(async (req, res, next) => { try { const { file } = req.body const contents = await readFilePromise(path.join(__dirname, file)) } catch (error) { throw createError(400, `File ${file} does not exist`) } })
4 404 معالجة الأخطاء
إذا مر الطلب بجميع معالجات الطرق المتوسطة ولكن لم تتم معالجتها ، فهذا يعني أنه لم يتم العثور على نقطة النهاية المقابلة لهذا الطلب.
لمعالجة أخطاء
404 Not Found
، يجب عليك إضافة معالج إضافي بين المسارات ومعالج الأخطاء. إليك ما يبدو عليه إنشاء كائن الخطأ 404:
تفاصيل الخطأ▍ ERR_HTTP_HEADERS_SENT ملاحظات الخطأ
لا تنزعج إذا شاهدت رسالة الخطأ
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
. تنشأ لأنه في نفس المعالج يتم استدعاء الطريقة التي تحدد رؤوس الاستجابة بشكل متكرر. فيما يلي الأساليب التي تستدعي تعيين رؤوس الاستجابة تلقائيًا:
- res.send
- res.json
- res.render
- res.sendFile
- res.sendStatus
- res.end
- res.redirect
لذلك ، على سبيل المثال ، إذا اتصلت
res.render
و
res.json
في معالج الاستجابة نفسه ،
ERR_HTTP_HEADERS_SENT
الخطأ
ERR_HTTP_HEADERS_SENT
:
app.get('/testing', (req, res) => { res.render('new-page') res.json({ message: '¯\_(ツ)_/¯' }) })
نتيجة لذلك ، إذا واجهت هذا الخطأ ، فتحقق بعناية من رمز معالج الاستجابة وتأكد من عدم وجود حالات يتم فيها استدعاء العديد من الطرق الموضحة أعلاه.
▍ معالجة الأخطاء وتدفق البيانات
إذا حدث خطأ ما أثناء تدفق الرد على الواجهة الأمامية ، فقد تواجه الخطأ نفسه
ERR_HTTP_HEADERS_SENT
.
في هذه الحالة ، يجب تمرير معالجة الأخطاء إلى المعالجات القياسية. سيرسل مثل هذا المعالج خطأ ويغلق الاتصال تلقائيًا.
app.use((error, req, res, next) => {
النتائج
أخبرتك اليوم بكل ما أعرفه عن معالجة الأخطاء في Express. آمل أن يساعدك هذا في كتابة تطبيقات Express أكثر موثوقية.
أعزائي القراء! كيف يمكنك التعامل مع الأخطاء في مشاريع Node.js الخاصة بك؟
