"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > GlobalErrorHandler: اكتشف الأخطاء التي تقع من خلال أصابع ErrorBoundary!

GlobalErrorHandler: اكتشف الأخطاء التي تقع من خلال أصابع ErrorBoundary!

تم النشر بتاريخ 2024-11-07
تصفح:492

GlobalErrorHandler: Catch the errors that falls through ErrorBoundary

ErrorBoundary هي أداة رائعة لالتقاط الأخطاء التي يتم طرحها من مكونات React. يمكنك تقديم رسائل خطأ مخصصة وفقًا لطبيعة الخطأ نفسه وموضعه. ولكن لا تتم معالجة جميع الأخطاء بواسطة ErrorBoundary! ماذا تفعل مع هؤلاء؟

عند النظر في كل من الأخطاء غير المتزامنة والأخطاء الصادرة من خارج React، فإن ErrorBoundary يكون قصيرًا. للتخفيف من هذا الأمر، قمت في تطبيقاتي بإنشاء ما أسميه GlobalErrorHandler. مكون وظيفي يقوم ببساطة أ) بفتح مربع حوار خطأ لإخبار المستخدم بحدوث خطأ ما ، ب) تسجيل الخطأ إلى الخادم، حتى نتمكن من التحقيق وإيجاد الحلول.

الفكرة بسيطة. نريد GlobalErrorHandler واحدًا في جذر تطبيقنا. يجب على هذا المعالج

معالجة الأخطاء التي لم يتم اكتشافها بواسطة ErrorBoundary فقط. علاوة على ذلك، يجب أن يرفضه المستخدم بسهولة، ويجب أن نفترض أن التطبيق لا يزال قابلاً للاستخدام.

لذا فإن الإستراتيجية هي كما يلي: لا يقوم GlobalErrorHandler بأي شيء على الإطلاق، باستثناء عرض أبنائه بشكل افتراضي. ولكنه يقوم بإعداد مستمعين للأحداث، يستمعان إلى كل الأخطاء وأحداث الرفض غير المعالجة في المتصفح. ثم يقوم بفحص الخطأ ومعرفة ما إذا كان قد تمت معالجته بالفعل بواسطة أي ErrorBoundaries. أخيرًا، إذا لم يكن الأمر كذلك، فسينبثق مربع حوار، يخبر المستخدم بحدوث خطأ ما في مكان ما، ويتيح للمستخدم تجاهل مربع الحوار ومتابعة استخدام التطبيق.

هل تمت معالجة الخطأ بالفعل؟

قبل إزعاج المستخدمين النهائيين بمربعات حوار غير ضرورية بالإضافة إلى المعالجة التي تتم بواسطة ErrorBoundary، علينا أولاً أن نبدأ بطرح الخطأ: هل تم التعامل معك بالفعل؟ الحل الذي أقترحه لهذا هو تقديم حقل جديد في كائن الخطأ وهو isHandledByBoundary. تم تعيين هذا على true ضمن ErrorBoundary:


ComponDidCatch(خطأ: خطأ، معلومات الخطأ: معلومات الخطأ) { (خطأ كأي).isHandledByBoundary = true; .... }
  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }
مع تطبيق هذا في جميع مكونات ErrorBoundary (والآلات الأخرى التي تعالج الأخطاء التي لم يتم اكتشافها)، نحن مستعدون للبدء في تحديد GlobalErrorHandler الخاص بنا.

الهيكل العظمي العاري

ثم يمكننا بناء الهيكل العظمي لـ GlobalErrorHandler الخاص بنا. فهو يعرض أطفاله بشكل مباشر، كما يعرض أيضًا "ErrorDialog" المحدد في مكان آخر. (إذا كنت تريد مشاركة هذا المكون عبر التطبيقات، فيمكن أن يكون ErrorDialog بمثابة دعامة بدلاً من ذلك.)


استيراد { useState، useEffect، ReactNode } من 'react'؛ استيراد { ErrorDialog } من '../Components/ErrorDialog'؛ اكتب الدعائم = { الأطفال: ReactNode؛ }; وظيفة التصدير GlobalErrorHandler({ children }: Props) { const [خطأ، setError] = useState(null); const [isDialogOpen, setDialogOpen] = useState(false); استخدام التأثير (() => { .... }, []); وظيفة مقبضCloseDialog() { setDialogOpen(false); setError(null); } يعود ( {أطفال} {isDialogOpen && خطأ && ( )} > ); }
  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }
الشيء الوحيد الذي ينقصنا الآن، هو معالجة الخطأ نفسه، المحدد في useEffect.

معالجة الأخطاء

جميع التعليمات البرمجية في هذا القسم يجب أن تكون موجودة داخل وظيفة useEffect!

أولاً نحدد HandleWindowError. سيتم تسليم هذا إلى معالج حدث الخطأ الموجود على كائن النافذة. لا يوجد شيء غامض هنا، ولكن لاحظ أن حدث الخطأ يحتوي أيضًا على معلومات حول المصدر ورقم السطر ورقم العمود. والتي قد تكون ذات قيمة للجمع.

عادةً ما يتم العثور على هذه المعلومات أيضًا داخل كائن الخطأ، ولكنني بحاجة إلى إجراء المزيد من التحقيقات التجريبية في هذا الشأن. ربما يجب علينا دائمًا الاحتفاظ بأرقام الأسطر والأعمدة كما أبلغ عنها حدث الخطأ؟ في هذه الحالة، يمكن أن يكون لدينا أيضًا حالة لهذا داخل GlobalErrorHandler (وتأكد من إرسالها عند تسجيل الخطأ).


وظيفة HandleWindowError ( الرسالة: سلسلة | حدث، المصدر؟: سلسلة، لينينو؟: رقم، كولنو؟: رقم، خطأ؟: خطأ ) { إذا (خطأ && (خطأ كأي).isHandledByBoundary) { عودة صحيحة؛ } const errorMessage = خطأ ؟ خطأ : `خطأ: ${message} في ${source}:${lineno}:${colno}`; setError(errorMessage); setDialogOpen(true); عودة صحيحة؛ }
  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }
سنقوم أيضًا بتعريف معالج HandleUnhandledRejection. هذا للأخطاء التي تظهر في الوعود، ولكن عندما نسينا كتابة جملة .catch()-plause.


الدالة HandleUnhandledRejection(event: PromiseRejectionEvent) { setError(`رفض الوعد غير المعالج: ${event.reason}`); setDialogOpen(true); }
  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }
ثم كل ما يتعين علينا القيام به، هو إعداد المستمعين، وإزالة المستمعين عندما لا يتم عرض GlobalErrorHandler بعد الآن:


window.addEventListener('error', HandleWindowError); window.addEventListener('unhandledrejection', HandleUnhandledRejection); العودة () => { window.removeEventListener('error', HandleWindowError); window.removeEventListener( "الرفض غير المعالج"، HandleUnhandledRejection ); };
  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }
بيانات الإرجاع هي بالطبع المكان الذي نعود فيه من الوظيفة التي نغذيها useEffect. وهذا يضمن أننا نبدأ في الاستماع إلى الأحداث والتعامل معها عند عرض المكون، والتوقف عندما لا يتم عرض المكون بعد الآن.

وبالتالي لدينا GlobalEventHandler، للتعامل مع تلك الأخطاء المزعجة في تطبيق React الخاص بنا والتي إما يتم طرحها من مصادر غير متزامنة، أو يتم طرحها من خارج مكونات React!

بيان الافراج تم إعادة نشر هذه المقالة على: https://dev.to/lebbe/globalerrorhandler-catch-the-errors-that-falls-through-errorboundarys-fingers-3m5d?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ [email protected] لحذفه
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3