So erfassen Sie Ausnahmen in React

So erfassen Sie Ausnahmen in React

Vorwort

Niemand ist perfekt, daher wird es immer Fehler im Code geben. Fehler sind nicht schlimm, der Schlüssel liegt darin, wie man mit ihnen umgeht.
Ich möchte Sie nur fragen, wie Fehler in React-Anwendungen erfasst werden? Zu diesem Zeitpunkt:

  • Xiaobai+++: Wie geht man damit um?
  • Xiaobai++: Fehlergrenze
  • Xiaobai+: ErrorBoundary, versuche es abzufangen
  • Xiaohei#: ErrorBoundary, versuche es mit „catch“, „window.onerror“
  • Xiaohei##: Das ist ein ernstes Problem. Ich kenne viele Möglichkeiten, damit umzugehen. Haben Sie eine bessere Lösung?

Fehlergrenze

EerrorBoundary kam in Version 16 heraus. Jemand fragte mich, was mit meiner Version 15 sei. Das wollte ich nicht hören. Ich verwende sowieso Version 16 und natürlich hat 15 unstable_handleError .

Auf der offiziellen Website von ErrorBoundary gibt es eine ausführliche Einführung, aber darum geht es nicht. Es geht darum, welche Ausnahmen es erfassen kann.

  • Rendern von untergeordneten Komponenten
  • Lebenszyklusfunktionen
  • Konstruktor
  • Klasse ErrorBoundary erweitert React.Component {
  Konstruktor(Requisiten) {
    super(Requisiten);
    dieser.Zustand = { hasError: false };
  }

  componentDidCatch(Fehler, Info) {
    // Fallback-Benutzeroberfläche anzeigen
    this.setState({ hasError: true });
    // Sie können den Fehler auch bei einem Fehlerberichtsdienst protokollieren
    logErrorToMyService(Fehler, Info);
  }

  rendern() {
    wenn (dieser.Zustand.hatFehler) {
      // Sie können jede benutzerdefinierte Fallback-Benutzeroberfläche rendern
      return <h1>Etwas ist schiefgelaufen.</h1>;
    }
    gib diese.Eigenschaften.Kinder zurück;
  }
}

<Fehlergrenze>
  <MeinWidget />
</Fehlergrenze>

Die Open-Source-Welt ist großartig. Ein großartiger Autor hat bereits eine hervorragende Bibliothek wie react-error-boundary zusammengestellt.
Sie müssen sich nur darum kümmern, was zu tun ist, wenn ein Fehler auftritt, und ihn dann zurücksetzen, perfekt.

importiere {ErrorBoundary} aus 'react-error-boundary'

Funktion ErrorFallback({Fehler, ResetErrorBoundary}) {
  zurückkehren (
    <div Rolle="Alarm">
      <p>Etwas ist schiefgelaufen:</p>
      <pre>{Fehlermeldung}</pre>
      <button onClick={resetErrorBoundary}>Erneut versuchen</button>
    </div>
  )
}

const ui = (
  <Fehlergrenze
    FallbackComponent={ErrorFallback}
    beim Zurücksetzen={() => {
      // setze den Status deiner App zurück, damit der Fehler nicht erneut auftritt
    }}
  >
    <Komponente, die einen Fehler verursachen kann />
  </Fehlergrenze>
)

Diese Fehler werden durch Fehlergrenzen leider nicht erkannt:

  • Ereignishandler
  • Asynchroner Code (z. B. setTimeout- oder requestAnimationFrame-Rückrufe)
  • Serverseitiger Rendering-Code
  • Fehlergrenzen Selbst ausgelöste Fehler

Den Originaltext finden Sie auf der offiziellen Website introduce-error-boundaries

Ziel dieses Artikels ist es, Fehler in Ereignishandlern zu erfassen.
Die offizielle Lösung sind „how-about-event-handlers“, also „try catch“.

Aber so viele Eventhandler, mein Gott, wie viele muss ich schreiben? . . . . . . . . . . . . . . . . . . .

  handleKlick() {
    versuchen {
      // Etwas tun, das
    } Fehler abfangen {
      this.setState({ Fehler });
    }
  }

Jenseits der Fehlergrenze

Sehen wir uns zunächst eine Tabelle an, in der die Mittel und der Umfang aufgelistet sind, mit denen wir Ausnahmen erfassen können.

Ausnahmetyp Synchrone Methoden Asynchrone Methoden Ressourcen laden Versprechen asynchron/warten
Versuchen/fangen
Fenster.beiFehler
Fehler
unbehandelte Ablehnung

Versuchen/fangen

Kann sowohl synchrone als auch asynchrone/wartende Ausnahmen abfangen.

window.onerror, Fehlerereignis

    window.addEventListener('Fehler', this.onError, true);
    window.onerror = dies.onError

window.addEventListener('error') kann mehr Ressourcen erfassen und Ausnahmen aufzeichnen als window.onerror.
Bitte beachten Sie, dass der letzte Parameter „true“ ist. Wenn er „false“ ist, funktioniert das Gerät möglicherweise nicht wie erwartet.
Wenn Sie nach der Bedeutung des dritten Parameters fragen, möchte ich natürlich nicht mit Ihnen sprechen. Tschüss.

unbehandelte Ablehnung

Beachten Sie, dass der letzte Parameter wahr ist.

window.removeEventListener('unbehandelte Ablehnung', this.onReject, true)

Es fängt nicht abgefangene Promise-Ausnahmen ab.

XMLHttpRequest und Fetch

XMLHttpRequest ist einfach zu handhaben und verfügt über ein eigenes Onerror-Ereignis.
Natürlich werden 99,99 % von Ihnen eine auf XMLHttpRequest basierende Bibliothek nicht selbst kapseln. Axios ist mit einem derart umfassenden Fehlerbehandlungsmechanismus wirklich gut.
Was das Apportieren betrifft: Wenn Sie selbst fangen und nicht damit umgehen, ist das Ihr eigenes Problem.
So viele, so schwierig.
Glücklicherweise gibt es tatsächlich eine Bibliothek react-error-catch, eine Komponente, die auf der Kapselung von ErrorBoudary, Fehlern und unbehandelten Ablehnungen basiert.
Der Kern ist wie folgt

   ErrorBoundary.prototype.componentDidMount = Funktion () {
        // Ereignis erfassen
        window.addEventListener('Fehler', this.catchError, true);
        // asynchroner Code
        window.addEventListener('unbehandelte Ablehnung', this.catchRejectEvent, true);
    };

verwenden:

Importiere ErrorCatch aus „react-error-catch“

const App = () => {
  zurückkehren (
  <FehlerCatch
      app="reagieren-fangen"
      Benutzer="cxyuns"
      Verzögerung={5000}
      max={1}
      Filter={[]}
      onCatch={(Fehler) => {
        console.log('Fehler gemeldet');
        // Ausnahmeinformationen an das Backend melden und dynamisch Tags erstellen new Image().src = `http://localhost:3000/log/report?info=${JSON.stringify(errors)}`
      }}
    >
      <Haupt />
    </ErrorCatch>)
}

Standard exportieren

Applaus, Applaus.
Tatsächlich ist dies nicht der Fall: Das Wichtigste an durch Fehler erfassten Fehlern besteht darin, dass sie Informationen zum Fehlerstapel bereitstellen, was für die Fehleranalyse, insbesondere nach der Verpackung, recht unfreundlich ist.
Es gibt so viele Fehler, deshalb werde ich mich zuerst mit den Ereignishandlern in React befassen.
Der Rest folgt: Fortsetzung folgt.

Ausnahmenerfassung in Eventhandlern

Beispiel

Meine Idee ist ganz einfach: Verwenden Sie einen Dekorator, um die ursprüngliche Methode neu zu schreiben.
Schauen wir uns zunächst die Verwendung an:

   @methodCatch({ message: "Bestellung konnte nicht erstellt werden", toast: true, report:true, log:true })
    asynchrone Reihenfolge erstellen() {
        const Daten = {...};
        const res = warte auf „Auftragserstellung“();
        wenn (!res || res.errCode !== 0) {
            return Toast.error("Bestellung konnte nicht erstellt werden");
        }
        
        .......
        Andere Codes, die Ausnahmen verursachen können …
        
       Toast.success("Bestellung erfolgreich erstellt");
    }

Beachten Sie die vier Parameter:

  • Meldung: Wenn ein Fehler auftritt, wird der Fehler
  • toast: Es ist ein Fehler aufgetreten, ob Toast
  • Bericht: Wenn ein Fehler auftritt, ob dieser gemeldet werden soll
  • log: Verwenden Sie console.error zum Drucken

Vielleicht werden Sie sagen, dass dies eine sichere und unbegründete Nachricht sei. Was wäre, wenn ich noch weitere Neuigkeiten hätte?
Zu diesem Zeitpunkt lächelte ich und sagte: „Keine Sorge, schauen wir uns einen anderen Code an.“

  @methodCatch({ message: "Bestellung konnte nicht erstellt werden", toast: true, report:true, log:true })
    asynchrone Reihenfolge erstellen() {
        const Daten = {...};
        const res = warte auf „Auftragserstellung“();
        wenn (!res || res.errCode !== 0) {
            return Toast.error("Bestellung konnte nicht erstellt werden");
        }
       
        .......
        Andere Codes, die Ausnahmen verursachen können …
        
       throw new CatchError("Bestellung konnte nicht erstellt werden, bitte kontaktieren Sie den Administrator", {
           Toast: wahr,
           Bericht: wahr,
           log: falsch
       })
       
       Toast.success("Bestellung erfolgreich erstellt");

    }

Ja, das stimmt, Sie können die Standardoptionen überschreiben, indem Sie einen benutzerdefinierten CatchError auslösen.
Diese Catch-Methode kann sowohl synchrone als auch asynchrone Fehler erfassen. Schauen wir uns den gesamten Code an.

Typdefinition

Exportschnittstelle CatchOptions {
    Bericht?: Boolesch;
    Nachricht?: Zeichenfolge;
    log?: boolesch;
    Toast?: Boolesch;
}

// Es ist sinnvoller, es in const.ts zu schreiben export const DEFAULT_ERROR_CATCH_OPTIONS: CatchOptions = {
    Bericht: wahr,
    Meldung: "Unbekannte Ausnahme",
    log: wahr,
    Toast: falsch
}

Benutzerdefinierter CatchError

importiere { CatchOptions, DEFAULT_ERROR_CATCH_OPTIONS } aus "@typess/errorCatch";

Exportklasse CatchError erweitert Fehler {

    öffentlicher __Typ__ = "__CATCH_ERROR__";
    /**
     * Fehler abgefangen * @param message message * @options andere Parameter */
    Konstruktor(Nachricht: Zeichenfolge, öffentliche Optionen: CatchOptions = DEFAULT_ERROR_CATCH_OPTIONS) {
        super(Nachricht);
    }
}

Dekorateure

Toast von „@components/Toast“ importieren;
importiere { CatchOptions, DEFAULT_ERROR_CATCH_OPTIONS } aus "@typess/errorCatch";
importiere { CatchError } von "@util/error/CatchError";


const W_TYPES = ["Zeichenfolge", "Objekt"];
Exportfunktion methodCatch(Optionen: Zeichenfolge | CatchOptions = DEFAULT_ERROR_CATCH_OPTIONS) {

    const type = Typ der Optionen;

    let opt: CatchOptions;

    
    if (options == null || !W_TYPES.includes(type)) { // null oder kein String oder Objekt opt ​​​​= DEFAULT_ERROR_CATCH_OPTIONS;
    } sonst wenn (Typ der Optionen === "Zeichenfolge") { // Zeichenfolge opt = {
            ...DEFAULT_ERROR_CATCH_OPTIONS,
            Nachricht: Optionen || DEFAULT_ERROR_CATCH_OPTIONS.message,
        }
    } sonst { // Gültiges Objekt opt ​​= { ...DEFAULT_ERROR_CATCH_OPTIONS, ...Optionen }
    }

    Rückgabefunktion (_target: beliebig, _name: Zeichenfolge, Deskriptor: PropertyDescriptor): beliebig {

        const oldFn = Deskriptor.Wert;

        Object.defineProperty(Deskriptor, "Wert", {
            erhalten() {
                asynchrone Funktion Proxy(...Argumente: beliebig[]) {
                    versuchen {
                        const res = warte auf oldFn.apply(this, args);
                        Rückgabewert;
                    } fangen (Fehler) {
                        // wenn (fehler Instanz von CatchError) {
                        wenn(err.__type__ == "__CATCH_ERROR__"){
                            err = err als CatchError;
                            const mOpt = { ...opt, ...(err.options || {}) };

                            wenn (mOpt.log) {
                                console.error("asyncMethodCatch:", mOpt.message || err.message , err);
                            }

                            wenn (mOpt.Bericht) {
                                // ZU TUN::
                            }

                            wenn (mOpt.toast) {
                                Toast.error(mOpt.message);
                            }

                        } anders {
                            
                            const Nachricht = Fehlernachricht || opt.Nachricht;
                            console.error("asyncMethodCatch:", Nachricht, Fehler);

                            wenn (opt.toast) {
                                Toast.error(Nachricht);
                            }
                        }
                    }
                }
                proxy._bound = wahr;
                Proxy zurückgeben;
            }
        })
        Rückgabedeskriptor;
    }
}

Um zusammenzufassen

Verwenden Sie Dekoratoren, um die ursprüngliche Methode zum Erfassen von Fehlern neu zu schreiben. Passen Sie die Fehlerklasse an und lösen Sie sie aus, um die Standardoptionen zu überschreiben. Erhöhte Flexibilität.

  @methodCatch({ message: "Bestellung konnte nicht erstellt werden", toast: true, report:true, log:true })
    asynchrone Reihenfolge erstellen() {
        const Daten = {...};
        const res = warte auf „Auftragserstellung“();
        wenn (!res || res.errCode !== 0) {
            return Toast.error("Bestellung konnte nicht erstellt werden");
        }
       Toast.success("Bestellung erfolgreich erstellt");
       
        .......
        Andere Codes, die Ausnahmen verursachen können …
        
       throw new CatchError("Bestellung konnte nicht erstellt werden, bitte kontaktieren Sie den Administrator", {
           Toast: wahr,
           Bericht: wahr,
           log: falsch
       })
    }

Nächster Schritt

Wie geht es weiter? Lassen Sie uns einen Schritt nach dem anderen angehen.
Nein, der Weg ist noch lang. Dies ist nur eine Basisversion.

Ergebnisse erweitern

@XXXFang
Klasse AAA{
    @YYYCatch
    Methode = () => {
    }
}

Abstrakt, abstrakt, abstrakt

Verabschiedung.

Abschließende Gedanken

Fehlergrenzen
Ausnahmebehandlung von React
Abfangen von Reaktionsfehlern
Erweiterter Ausnahmebehandlungsmechanismus von React – Fehlergrenzen
Dekorateur
Kerndekorateure
autobind.js

Dies ist das Ende dieses Artikels zum eleganten Erfassen von Ausnahmen in React. Weitere Inhalte zum Erfassen von Ausnahmen in React finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Kapseln Sie eine einfachste ErrorBoundary-Komponente zur Behandlung von React-Ausnahmen
  • Detaillierte Erklärung der Ausnahmebehandlung in React 16

<<:  Die MySQL-Datenbankmigration exportiert und importiert schnell große Datenmengen

>>:  So lösen Sie das Problem der Zabbix-Überwachung, das aufgrund von PHP-Problemen zu verstümmelten chinesischen Zeichen in der grafischen Benutzeroberfläche führt

Artikel empfehlen

Die perfekte Lösung für das AutoFill-Problem in Google Chrome

In Google Chrome werden Sie nach der erfolgreiche...

Spezifischer Einsatz von Routing Guards in Vue

Inhaltsverzeichnis 1. Globale Wache 1.1 Globaler ...

Detaillierte Erläuterung des mobilen Projekts vite2.0 + vue3

1. Technische Punkte Vite-Version vue3 ts Integri...

So zeigen Sie alle laufenden Prozesse in Linux an

Sie können den Befehl ps verwenden. Es kann relev...

Detaillierte Erläuterung des MySQL-Isolationsebenen-Operationsprozesses (cmd)

Beispielvorgang für nicht festgeschriebenes Lesen...

So schreiben Sie den Nofollow-Tag und verwenden ihn

Das „nofollow“-Tag wurde vor einigen Jahren von G...

So installieren Sie MySql in CentOS 8 und erlauben Remoteverbindungen

Herunterladen und installieren. Prüfen Sie zunäch...

CentOS 8 ist jetzt verfügbar

CentOS 8 ist jetzt verfügbar! Die Versionen von C...

So stellen Sie ein SpringBoot-Projekt mit Docker bereit

Die Entwicklung der Docker-Technologie bietet ein...

So gestalten Sie die Homepage von Tudou.com

<br />Ich arbeite seit mehreren Jahren im Fr...