So erfassen und analysieren Sie den JavaScript -Fehler
Front-End-Ingenieure wissen alle, dass JavaScript grundlegende Funktionen für Ausnahmebereitschaften hat. Wir können einen neuen Fehler () werfen, und der Browser macht auch eine Ausnahme, wenn wir den API -Fehler aufrufen. Es wird jedoch geschätzt, dass die meisten Front-End-Ingenieure nicht darüber nachgedacht haben, diese außergewöhnlichen Informationen zu sammeln. Solange sich die Aktualisierung nach einem JavaScript -Fehler nicht vermehrt, kann der Benutzer das Problem durch Auffrischen lösen, und der Browser stürzt nicht ab, und es wird in Ordnung sein, wenn es nicht passiert ist. Diese Annahme war der Fall, bevor die einseitige App populär wurde. Die aktuelle Single -Page -App ist äußerst komplex, nachdem sie einen bestimmten Zeitraum ausgeführt haben. Würden Sie die vorherigen Operationen nicht vollständig überarbeiten? Daher müssen wir diese Ausnahmeinformationen erfassen und analysieren, und dann können wir den Code ändern, um zu vermeiden, dass die Benutzererfahrung beeinflusst wird.
Wie man Ausnahmen fängt
Wir haben uns geschrieben, einen neuen Fehler (). Ausnahmen, die beim Aufrufen der Browser -API auftreten, sind jedoch nicht unbedingt so einfach zu erfassen. Für das erstere können wir es auch durch Try-Catch fangen, für das letztere müssen wir auf globale Ausnahmen hören und es dann fangen.
Versuche
Wenn bekannt ist, dass einige Browser-APIs Ausnahmen werfen, müssen wir den Anruf in den Versuch einsetzen, um das gesamte Programm aufgrund von Fehlern in einen illegalen Zustand einzugeben. Zum Beispiel ist Window.LocalStorage eine solche API.
Die Codekopie lautet wie folgt:
versuchen {
LocalStorage.SetItem ('Datum', Datum.Now ());
} catch (error) {
ReporterRor (Fehler);
}
Ein weiteres gängiges Try-Catch-Szenario sind Rückrufe. Da der Code der Rückruffunktion unkontrollierbar ist, wissen wir nicht, wie gut der Code ist und ob andere APIs, die Ausnahmen werfen, aufgerufen werden. Damit keine anderen Codes nach dem Aufrufen des Rückrufs aufgrund von Rückruffehlern ausgeführt werden können, muss der Anruf wieder in den Versuchs-Catch gesteckt werden.
Die Codekopie lautet wie folgt:
Hörer.foreach (Funktion (Hörer) {
versuchen {
Hörer();
} catch (error) {
ReporterRor (Fehler);
}
});
window.onError
Für Orte, die Try-Catch nicht abdecken können, kann sie nur über das Fenster.
Die Codekopie lautet wie folgt:
window.onError =
Funktion (ErrorMessage, Scripturi, Leinenumber) {
Reporterror ({{
Nachricht: ErrorMessage,
Skript: scripturi,
Zeile: Leinenumberne
});
}
Achten Sie darauf, nicht klug zu sein und verwenden Sie Window.AdDeventListener oder Window.attachevent, um Window.onError anzuhören. Viele Browser implementieren nur Fenster. In Anbetracht der Tatsache, dass der Standardentwurf auch Window.OnError definiert, müssen wir nur Windows.onError verwenden.
Eigentum fehlen
Angenommen, wir haben eine Reporterror-Funktion, um gefangene Ausnahmen zu sammeln und sie dann in Stapel an serverseitige Speicher für Abfrage und Analyse zu senden. Welche Informationen möchten wir sammeln? Weitere nützliche Informationen sind: Fehlertyp (Name), Fehlermeldung (Nachricht), Skriptdateiadresse (Skript), Zeilennummer (Zeile), Spaltennummer (Spalte) und Stapelverfolgung. Wenn eine Ausnahme über Try-Catch erfasst wird, befinden sich alle diese Informationen auf dem Fehlerobjekt (unterstützt von Mainstream-Browsern), sodass Reporterror diese Informationen auch sammeln kann. Wenn es jedoch über window.onError erfasst wird, wissen wir alle, dass diese Ereignisfunktion nur 3 Parameter enthält, sodass andere Informationen als diese 3 Parameter verloren gehen.
Serialisieren Sie Nachrichten
Wenn das Fehlerobjekt von uns selbst erstellt wird, wird die Message von uns gesteuert. Grundsätzlich, was wir in Fehler einfügen. (Der Browser modifiziert tatsächlich eine kleine Änderung, z. B. das Hinzufügen des "Uncorved -Fehler Sie im Fenster. Dies ist natürlich auf das Fehlerobjekt beschränkt, das wir selbst erstellt haben.
Der fünfte Parameter
Die Browserhersteller kennen auch die Einschränkungen, denen Menschen bei der Verwendung von window.onError unterliegen, und fügen damit beginnen, Windows.onError neue Parameter hinzuzufügen. In Anbetracht der Tatsache, dass nur Zeilennummern und keine Spaltennummern sehr symmetrisch zu sein scheinen, haben er zuerst die Spaltenzahlen hinzugefügt und sie im vierten Parameter platziert. Was jedoch jeder mehr besorgt ist, ist, ob sie den gesamten Stapel bekommen können, so dass Firefox sagte, es wäre besser, den Stapel in den fünften Parameter zu setzen. Chrome sagte jedoch, dass es besser wäre, das gesamte Fehlerobjekt in den fünften Parameter zu setzen. Da Chrome schneller ist, wurde in Chrome 30 ein neues Fenster in der Eerror -Signatur implementiert, was zum folgenden Schreiben des Standardentwurfs führte.
Die Codekopie lautet wie folgt:
Fenster.onError = Funktion (
Errormessage,
scripturi,
Leinenumme,
Spaltennummer,
Fehler
) {
if (Fehler) {
ReporterRor (Fehler);
} anders {
Reporterror ({{
Nachricht: ErrorMessage,
Skript: scripturi,
Linie: Leinenumberne,
Spalte: Spaltennummer
});
}
}
Regelmäßigkeit der Attribute
Die Namen der Fehlerobjekte, die wir zuvor diskutiert haben, basieren auf Chrome -Benennungsmethoden. Daher benötigen wir auch eine spezielle Funktion, um das Fehlerobjekt zu normalisieren, dh verschiedene Attributnamen einem einheitlichen Attributnamen zuzuordnen. Für bestimmte Praktiken finden Sie in diesem Artikel. Obwohl die Browser -Implementierung aktualisiert wird, wird es für Menschen nicht zu schwierig sein, eine solche Zuordnungstabelle beizubehalten.
Ähnlich ist das Stack Trace -Format. Diese Eigenschaft speichert die Stapelinformationen einer Ausnahme, wenn sie in Form von einfachem Text auftritt. . Name (Kennung), Datei (Skript), Zeile (Zeile) und Spalte (Spalte).
Sicherheitsbeschränkungen
Wenn Sie auch auf einen Fehler mit der Meldung "Skript -Fehler" gestoßen sind, werden Sie verstehen, wovon ich spreche, was tatsächlich die Einschränkungen des Browsers für Skriptdateien aus verschiedenen Quellen ist. Der Grund für diese Sicherheitsbeschränkung ist wie folgt: Angenommen, die von einem Online-Bankier zurückgegebene HTML nach der Anmeldung unterscheidet sich von der HTML, die von einem anonymen Benutzer gesehen wird. Eine Website von Drittanbietern kann die URI dieser Online-Bank in das Skript einbringen. SRC -Attribut. Natürlich kann HTML nicht als JS analysiert werden, daher stellt der Browser eine Ausnahme aus, und diese Website von Drittanbietern kann feststellen, ob der Benutzer angemeldet ist, indem der Standort der Ausnahme analysiert wird. Aus diesem Grund filtert der Browser alle Ausnahmen, die von verschiedenen Quell -Skriptdateien geworfen werden, und hinterlässt nur eine unveränderte Nachricht wie "Skriptfehler". Alle anderen Attribute verschwinden.
Für Websites einer bestimmten Skala ist es normal, dass Skriptdateien auf CDNs platziert werden und verschiedene Quellen platziert werden. Selbst wenn Sie selbst eine kleine Website erstellen, können gemeinsame Frameworks wie JQuery und Backbone die Version der öffentlichen CDN direkt verweisen, um Benutzer -Downloads zu beschleunigen. Diese Sicherheitsbeschränkung verursacht also einige Probleme, was die Ausnahmeinformationen verursacht, die wir von Chrome und Firefox sammeln, als nutzloser "Skriptfehler".
CORS
Wenn Sie diese Einschränkung umgehen möchten, stellen Sie einfach sicher, dass die Skriptdatei und die Seite selbst gleich sind. Aber würden die Einlegen von Skriptdateien auf Servern, die nicht von CDN beschleunigt werden, die Download -Geschwindigkeit des Benutzers verringern? Eine Lösung besteht darin, die Skriptdatei weiterhin auf dem CDN zu platzieren, mit XMLHTTPREQUET den Inhalt wieder durch CORs herunterzuladen und dann ein <skript> -Tag zu erstellen, um sie in die Seite zu injizieren. Der in der Seite eingebettete Code ist natürlich der gleiche Ursprung.
Dies ist einfach zu sagen, aber es gibt viele Details zu implementieren. Ein einfaches Beispiel geben:
Die Codekopie lautet wie folgt:
<script src = "http://cdn.com/step1.js"> </script>
<Script>
(Funktion Step2 () {}) ();
</script>
<script src = "http://cdn.com/step3.js"> </script>
Wir alle wissen, dass, wenn es in Schritt1, Schritt 2 und Schritt 3 Abhängigkeiten gibt, es ausschließlich in dieser Reihenfolge ausgeführt werden muss, sonst kann ein Fehler auftreten. Der Browser kann parallel Schritt 1- und Schritt3 -Dateien anfordern, die Bestellung ist jedoch bei der Ausführung garantiert. Wenn wir den Dateiinhalt von Schritt1 und Schritt 3 mit XMLHTTPREquest erhalten, müssen wir die richtige Reihenfolge selbst sicherstellen. Vergessen Sie nicht, dass Schritt 2 ausgeführt werden kann.
Wenn wir bereits über einen vollständigen Satz von Tools verfügen, um <script> Tags für verschiedene Seiten auf der Website zu generieren, müssen wir diesen Satz von Tools anpassen, um Änderungen an <Script> -Tags vorzunehmen:
Die Codekopie lautet wie folgt:
<Script>
Scheduleremotescript ('http://cdn.com/step1.js');
</script>
<Script>
planInLineScript (Funktionscode () {
(Funktion Step2 () {}) ();
});
</script>
<Script>
Scheduleremotescript ('http://cdn.com/step3.js');
</script>
Wir müssen die beiden Funktionen Scheduleremotescript und planInLineScript implementieren und sicherstellen, dass sie vor dem ersten <skript> -Tag definiert sind, mit dem die externe Skriptdatei verweist, und dann werden die verbleibenden <Script> -Tags in das obige Formular umgeschrieben. Beachten Sie, dass die sofort ausgeführte Step2 -Funktion in einer größeren Codefunktion platziert wurde. Die Codefunktion wird nicht ausgeführt, sondern nur ein Container, so dass der ursprüngliche Schritt2 -Code ohne Flucht beibehalten wird, aber nicht sofort ausgeführt wird.
Als nächstes müssen wir einen vollständigen Mechanismus implementieren, um sicherzustellen, dass der von Scheduleremotescript basierende Dateiinhalt basierend auf der Adresse und dem von planInLinescript direkt erhaltenen Code einzeln in der richtigen Reihenfolge ausgeführt werden kann. Ich werde den detaillierten Code hier nicht geben, wenn Sie interessiert sind, können Sie ihn selbst implementieren.
Zeilennummerprüfung
Wenn Sie Inhalte über CORS und das Einfügen von Code in die Seite erhalten, können Sie Sicherheitsbeschränkungen durchbrechen. Es wird jedoch ein neues Problem einführen, dh Konflikte für die Zeilennummer. Ursprünglich könnte die eindeutige Skriptdatei über Fehler.Script und dann die eindeutige Zeilennummer über Fehler.Line gefunden werden. Da sie alle in der Seite eingebetteten Codes sind, können mehrere <Script> -Tags nicht durch Fehler unterschieden werden. .
Um Zeilennummernkonflikte zu vermeiden, können wir einige Zeilennummern so verschwenden, damit sich die vom tatsächlichen Code in jedem <skript> -Tag verwendeten Zeilennummernintervalle nicht miteinander überlappen. Angenommen, der tatsächliche Code in jedem <skript> -Tag überschreitet beispielsweise 1000 Zeilen, kann ich den Code im ersten <skript> -TAG -Tag aufnehmen Zeile 11000 und im zweiten <Skript> -Antag des Codes im Code belegen Zeile ein 10012000 (1000 leere Zeilen wurden vor dem Einfügen eingefügt), der Code des dritten <script> -Tags belegt Zeile 20013000 (2000 leere Zeilen wurden vor dem Einfügen eingefügt) und so weiter. Anschließend verwenden wir das Datenattribut, um diese Informationen für eine einfache Rückprüfung aufzuzeichnen.
Die Codekopie lautet wie folgt:
<Skript
data-src = "http://cdn.com/step1.js"
Data-Line-Start = "1"
>
// Code für Schritt 1
</script>
<skript data-line-start = "1001">
// '/n' * 1000
// Code für Schritt 2
</script>
<Skript
data-src = "http://cdn.com/step3.js"
Data-Line-Start = "2001"
>
// '/n' * 2000
// Code für Schritt 3
</script>
Nach dieser Verarbeitung bedeutet dies, wenn ein Fehlerfehler 3005 beträgt, dass der tatsächliche Fehler. Wir können diese Zeilennummer -Überprüfung der zuvor erwähnten ReporterRor -Funktion durchführen.
Da wir nicht garantieren können, dass jede Skriptdatei nur 1000 Zeilen enthält, ist es auch möglich, dass einige Skriptdateien wesentlich weniger als 1000 Zeilen sind. Daher müssen jedem <Script> -Tag nicht ein 1000 Zeilenintervall zugewiesen. Wir können Intervalle basierend auf der tatsächlichen Anzahl von Skriptlinien zuweisen und nur sicherstellen, dass die von jedem <Script> -Tag verwendeten Intervalle nicht überlappen.
Crossorigin -Attribut
Die Sicherheitsbeschränkungen, die Browser für Inhalte aus verschiedenen Quellen auferlegt haben, sind natürlich nicht auf <Script> -Tags beschränkt. Da XMLHTTPREquest diese Einschränkung durch CORs durchbrechen kann, warum werden Ressourcen direkt über Tags verwiesen, die nicht zulässig sind? Das ist sicherlich in Ordnung.
Die Einschränkung der Verweise auf verschiedene Quell -Skriptdateien für <Script> -Tags gilt auch für die Verweise auf verschiedene Quellbilddateien für <MeMG> -Tags. Wenn ein <img> -Tag eine andere Quelle ist, die einmal in der Zeichnung <Canvas> verwendet wird, wird die <Canvas> zu einem geschriebenen Zustand, sodass die Website nicht autorisierte Bilddaten aus verschiedenen Quellen über JavaScript stehlen kann. Später löste das <img> Tag dieses Problem durch Einführung des Crossorigin -Attributs. Wenn Crossorigin = "Anonymous" ist, entspricht es anonyme CORs;
Warum kann das <Script> -Tag dies nicht <img> tag dies können? Daher fügte der Browserhersteller das gleiche Crossorigin -Attribut zum <Script> -Tag hinzu, um die oben genannten Sicherheitsbeschränkungen zu lösen. Jetzt ist die Unterstützung von Chrome und Firefox für diese Eigenschaft völlig kostenlos. Safari behandelt Crossorigin = "Anonymous" als Crossorigin = "Anwendungszüchter", und das Ergebnis ist, dass Safari die Authentifizierung als Fehler behandelt, wenn der Server nur anonyme CORs unterstützt. Da der CDN -Server aus Leistungsgründen nur statische Inhalte zurückgibt, ist es unmöglich, den HTTP -Header dynamisch zurückzugeben, um CORs basierend auf Anfragen zu authentifizieren.
Zusammenfassen
Die Handhabung der JavaScript -Ausnahme sieht einfach aus und unterscheidet sich nicht von anderen Sprachen, aber es ist nicht so einfach, alle Ausnahmen zu fangen und die Eigenschaften zu analysieren. Obwohl einige Dienste von Drittanbietern jetzt Google Analytics-Dienste anbieten, die JavaScript-Ausnahmen erfassen, müssen Sie dies selbst tun, wenn Sie die Details und Prinzipien verstehen möchten.