So suchen Sie im Frontend nach Fehlern: 4 Hauptphasen


In diesem Artikel werde ich das Problem der Identifizierung und Behandlung von Fehlern behandeln, die im Frontend (Browser oder Webansicht) auftreten.

Im Frontend wird JS-Code im Browser ausgeführt. JavaScript ist keine kompilierte Sprache, daher besteht bei direkter Verwendung des Programms immer die Möglichkeit eines Leistungsfehlers. Ein Ausführungsfehler blockiert den Code nach dem Fehlerort, und Benutzer des Programms laufen Gefahr, bei einem nicht funktionsfähigen Anwendungsbildschirm zu bleiben, der nur neu geladen oder geschlossen werden kann. Es gibt jedoch Methoden zur Erkennung von Fehlern und deren sicherer Begleitung, um solche Situationen zu vermeiden.

1. JavaScript-Tools


Try / Catch-Blöcke


Möglicherweise fehlgeschlagene Funktionen werden möglicherweise in Try / Catch-Blöcke eingeschlossen. Zunächst versucht das Programm, den Code im try-Block auszuführen. Wenn aus irgendeinem Grund die Codeausführung unterbrochen ist, wechselt das Programm in den catch-Block, in dem drei Parameter verfügbar sind:

  • Name - standardisierter Name des Fehlers;
  • Nachricht - Nachricht über die Details des Fehlers;
  • Stack - Der aktuelle Aufrufstapel, in dem der Fehler aufgetreten ist.

Also:

try {

   callFunc();

} catch (e) {

   console.log(e.name) // ReferenceError

   console.log(e.message) // callFunc is not defined

   console.log(e.stack) // ReferenceError: callFunc is not defined at window.onload

}

Für den Entwickler ist die Hauptsache, dass das Programm die Ausführung nach dem catch-Block fortsetzen kann. Somit wird die Benutzerinteraktion nicht unterbrochen.

Mit dem Try / Catch-Block können Sie auch eigene Fehler verursachen, z. B. beim Überprüfen von Daten:

const user = {

  name : «Mike»

};

try {

   if (!user.age) throw new SyntaxError(«User age is absent!»);

} catch (e) {

   console.log(e.name) // SyntaxError

   console.log(e.message) // User age is absent!

   console.log(e.stack) // SyntaxError: User age is absent! at window.onload

}

Schließlich können Sie diese Anweisung um einen weiteren Block erweitern - schließlich, der immer ausgeführt wird: sowohl für den Fall, dass beim Versuch kein Fehler aufgetreten ist, als auch für den Fall, dass das Steuerelement an den catch-Block übergeben wurde:

try {

   callFunc();

} catch (e) {

   console.log(e)

} finally {

   ...

}

Manchmal verwenden sie die try / finally-Anweisung (ohne catch), damit Sie den Code weiterhin verwenden können, ohne bestimmte Fehler zu behandeln.

Window.onerror-Ereignis


Es ist oft nützlich zu wissen, dass das Skript auf der Seite fehlerhaft ist, auch wenn das Programm fehlerhaft ist und die Benutzersitzung nicht erfolgreich beendet wurde. Normalerweise werden diese Informationen dann in Fehlerprotokollierungssystemen verwendet.

Das globale Fensterobjekt hat ein Fehlerereignis ( verwenden Sie es vorsichtig: Die Implementierung kann in verschiedenen Browsern unterschiedlich sein! ):

window.onerror = function(message, url, line, col, error) {

   console.log(`${message}\n  ${line}:${col}  ${url}`);

};

Wenn Sie diesen Code am Anfang des Skripts platzieren oder ihn zunächst in ein separates Skript laden, stehen dem Entwickler für Fehler unten detaillierte Informationen zur Verfügung.

Vollständige Informationen sind jedoch nur für Skripte verfügbar, die von derselben Domain heruntergeladen wurden. Wenn das fehlerhafte Skript aus einer anderen Domäne geladen wird, funktioniert window.onerror, es werden jedoch keine Details zum Fehler angezeigt.

Framework-Komponenten


Einige JS-Frameworks ( React , Vue) bieten ihre eigenen Fehlerbehandlungslösungen an. Beispielsweise kann React an der Stelle des Blocks, in dem der Fehler aufgetreten ist, ein spezielles Layout zeichnen:

class ErrorBoundary extends React.Component {

   constructor(props) {

       super(props);

       this.state = { hasError: false };

   }

   static getDerivedStateFromError(error) {

       //    ,      UI.

       return { hasError: true };

   }

   componentDidCatch(error, errorInfo) {

       //           

       logErrorToMyService(error, errorInfo);

   }

   render() {

       if (this.state.hasError) {

           //    UI  

           return <h1>-   .</h1>;

       }

       return this.props.children;

   }

}

<ErrorBoundary>

   <MyWidget />

</ErrorBoundary>

Tatsächlich ist die React-Komponente in eine spezielle Komponente eingebunden, die Fehler behandelt. Dies ähnelt dem Umschließen von Funktionen mit einem try / catch-Konstrukt.

2. Projektmontagewerkzeuge


Moderne JS-Skripte werden normalerweise transpiliert. Das heißt, die Entwicklung erfolgt nach den neuesten ES-Standards. Anschließend wird der Code des Entwicklers, der den Project Builder verwendet (z. B. Webpack), in Code konvertiert, der garantiert in der ausgewählten Anzahl von Browsern funktioniert.

In der Erstellungsphase wird der Code auf korrekte Syntax überprüft. Eine offene Klammer oder eine falsche Bezeichnung eines Klassenfelds führt sofort zu einem Fehler bei der Montage, und das Bündel wird einfach nicht zusammengebaut. Der Entwickler muss solche Fehler sofort beheben, um weiterarbeiten zu können.

Der Kollektor schlägt möglicherweise auch vor, dass einige Codeteile beim Ausführen des Programms nicht verwendet werden. Vielleicht veranlasst dies den Entwickler, über eine eingehendere Untersuchung des Codes nachzudenken, was sich indirekt auf die Identifizierung neuer Fehler auswirken kann.

3. Testen


Eine andere Möglichkeit, Fehler im Code zu vermeiden, besteht darin, ihn zu testen. Im Frontend befinden sich Tools für den effektiven Einsatz von Unit-Tests. Typischerweise werden Frameworks wie Jest, Karma, Mocha, Jasmine verwendet. Zusammen mit Test-Frameworks verwenden sie häufig Erweiterungen wie Enzyme, React Testing Library, Sinon und andere, die es ermöglichen, Tests mithilfe von Spott-, Spionage- und anderen Tools zu bereichern.

Bei der Suche nach Fehlern sind Tests in erster Linie nützlich, um eine Vielzahl von Daten zu laden, die zu Ausführungsfehlern führen können. Der folgende Code besteht also die Syntaxvalidierung und funktioniert wie erwartet:

const func = (data) => {

   return JSON.parse(data)

}

func('{«a»:1}')

Es wird jedoch unterbrochen, wenn Sie den falschen Wert angeben:

func() // Uncaught SyntaxError: Unexpected token u in JSON at position 0.


Dieser Code besteht auch die Validierung während der Montage:

const obj = {

   outer : {

       last : 9

   }

}

if (obj.outer.inner.last) {

   console.log(«SUCCESS»)

}

Es wird jedoch auch während der Ausführung unterbrochen. Nach dem Testen wird der Entwickler wahrscheinlich zusätzliche Überprüfungen durchführen:

if (obj.outer?.inner?.last) {

   console.log(«SUCCESS»)

}

Solche Fehler treten häufig auf, wenn Daten vom Server empfangen werden (z. B. mit einer AJAX-Anforderung) und anschließend analysiert werden. Durch Testen des Codes können Sie im Voraus Fälle identifizieren und beseitigen, in denen der Code während der Ausführung im Browser des Clients beschädigt werden kann.

4. Protokollierung


Angenommen, wir haben alle möglichen Maßnahmen ergriffen, um Fehler bei der Entwicklung und Montage des Projekts zu vermeiden. Fehler können jedoch weiterhin produktiven Code infiltrieren. Wir müssen irgendwie etwas über ihre Anwesenheit herausfinden und sofort Korrekturmaßnahmen ergreifen. Es ist nicht die beste Option, Benutzer zu bitten, eine Browserkonsole zu öffnen und Screenshots zu machen. Daher ist es gut, die Fehlerprotokollierung mit dem Projekt zu verbinden.

Die Bedeutung ist einfach: Für jedes window.onerror-Ereignis oder jeden Übergang der Codeausführung zum catch-Block wird eine einfache AJAX-Anforderung an eine speziell zugewiesene Serveradresse gesendet, in deren Hauptteil Informationen über den Fehler eingefügt werden. Als Nächstes benötigen Sie ein Tool, das den technischen Support und die Entwickler schnell über das Vorhandensein neuer Fehler informiert und es Ihnen ermöglicht, effektiv mit ihnen zu arbeiten. Das beliebteste dieser Frontend-Tools ist Sentry.

Mit dem Sentry-Protokollierungssystem können Sie Fehler in Echtzeit erfassen, gruppieren und präsentieren. Es gibt Assemblys für verschiedene Sprachen, einschließlich JavaScript. Das Projekt bietet kostenpflichtigen Zugriff mit erweiterten Funktionen für Unternehmen. Sie können die Hauptfunktionen jedoch auf einem kostenlosen Testkonto testen.

Sentry kann sowohl direkt in der HTML-Datei als auch in Komponenten verbunden werden, die auf einem der gängigen Frameworks ausgeführt werden: React, Vue, Angular, Ember und andere.

Laden Sie das Skript, um die Protokollierungsfunktionen direkt im Browser im Abschnitt zu verbinden:

<script

   src=«https://browser.sentry-cdn.com/5.13.0/bundle.min.js»

   integrity=«sha384-ePH2Cp6F+/PJbfhDWeQuXujAbpil3zowccx6grtsxOals4qYqJzCjeIa7W2UqunJ»

   crossorigin="anonymous"></script>


Als nächstes initialisieren wir im JS-Code:

Sentry.init({

   dsn: 'https://<your account key here>@sentry.io/<your project id here>'

});

Alle. Wenn im Code unter dieser Zeile ein Fehler auftritt, protokolliert Sentry ihn. Protokolle werden auch dann aufgezeichnet, wenn der Fehler aufgrund eines Fehlers von Skripten aus anderen Domänen aufgetreten ist:



Sentry bietet ausreichend Gelegenheit, eine Reihe von Fehlermeldungen zu analysieren und Benachrichtigungen zu konfigurieren. Es ist auch möglich, Fehlerprotokolle nach den Versionen Ihres Produkts zu gruppieren:

Sentry.init({

   dsn: 'https://<your account key here>@sentry.io/<your project id here>',

   release: '2020.03.06.1'

});

Mit Sentry können Statistiken verwendet werden, um den Kontext eines Fehlers zu übertragen, z. B. Kundeninformationen, Fingerabdruck, Fehlerstufe (schwerwiegend, Fehler, Warnung, Info, Debug) und Tag.

Es ist möglich, Benutzerereignisse in Statistiken aufzuzeichnen. Sie können beispielsweise die Nachverfolgung festlegen, um die Größe des Browserfensters zu ändern oder eine AJAX-Anforderung zu stellen. Sentry hat auch ein eigenes Widget mit einem Feedback-Fenster, das dem Benutzer im Fehlerfall angezeigt werden kann. Dies liefert zusätzliche Informationen, um die Umstände des Fehlers zu untersuchen.

Um Sentry zusammen mit den Frameworks bereitzustellen, installieren Sie einfach das Paket und stellen Sie eine Verbindung her:

# Using yarn

yarn add @sentry/browser

# Using npm

npm install @sentry/browser


Wir initialisieren im Hauptskript des Projekts (für React und Angular):

import * as Sentry from «@sentry/browser»;

Sentry.init({ dsn: 'https://<your account key here>@sentry.io/<your project id here>' });


Für Vue und Ember übergeben wir eine weitere erforderliche Konfigurationszeile:

# Vue

Sentry.init({

   dsn: '<your account key here>@sentry.io/<your project id here>',

   integrations: [new Integrations.Vue({Vue, attachProps: true})],

});

# Ember

Sentry.init({

   dsn: '<your account key here>@sentry.io/<your project id here>',

   integrations: [new Integrations.Ember()]

});

Das Integrationspaket wird separat installiert:

# Using yarn

yarn add @sentry/integrations

# Using npm

npm install @sentry/integrations

Um Konflikte und doppelte Informationen beim Verbinden mehrerer Skripts in einem Projekt zu vermeiden, können Sie mit Sentry für jede Protokollierungsinitialisierung einen separaten Client erstellen:

import { BrowserClient } from «@sentry/browser»;

const client = new BrowserClient({

   dsn: '<your account key here>@sentry.io/<your project id here>',

});

client.captureException(new Error('example'));

Die Projektwebsite enthält eine detaillierte Dokumentation mit Anwendungsbeispielen: https://docs.sentry.io .

Dieser Artikel wurde mit Unterstützung der Cloud-Plattform Mail.ru Cloud Solutions erstellt .

Was gibt es sonst noch zu diesem Thema zu lesen:

  1. Reaktierbare Reaktionskomponenten: So beenden Sie das Schreiben derselben .
  2. So vermeiden Sie Fehler bei der Entwicklung von React .
  3. - .

All Articles