Un autre scénario applicable à try-catch est le rappel. . Étant donné que le code de la fonction de rappel est hors de notre contrôle, nous n'avons aucune idée de la qualité du code ni si d'autres API qui lanceront des exceptions seront appelées. Afin d'éviter que d'autres codes après l'appel du rappel ne puissent s'exécuter en raison d'erreurs de rappel, il est nécessaire de remettre l'appel dans try-catch.
Pour les zones qui ne sont pas couvertes par try-catch, si une exception se produit, elle ne peut être capturée que via window.onerror.
window.onerror =
function( errorMessage, scriptURI , lineNumber) {
reportError({
message: errorMessage,
script: scriptURI,
line: lineNumber
});
Faites attention à ne pas être malin et utilisez window.addEventListener ou window.attachEvent pour écouter window.onerror. De nombreux navigateurs implémentent uniquement window.onerror, ou seule l'implémentation de window.onerror est standard. Considérant que le projet de norme définit également window.onerror, nous pouvons simplement utiliser window.onerror.
Attributs perdus
Supposons que nous ayons une fonction reportError pour collecter les exceptions capturées, puis les envoyer au stockage côté serveur par lots pour interrogation et analyse, alors quelles informations souhaitons-nous collecter ? Les informations les plus utiles incluent : le type d'erreur (nom), le message d'erreur (message), l'adresse du fichier de script (script), le numéro de ligne (ligne), le numéro de colonne (colonne) et la trace de la pile (pile). Si une exception est interceptée via try-catch, ces informations se trouvent sur l'objet Error (pris en charge par les navigateurs grand public), donc reportError peut également collecter ces informations. Mais si elle est capturée via window.onerror, nous savons tous que cette fonction événementielle n'a que 3 paramètres, donc les informations autres que ces 3 paramètres sont perdues.
Message sérialisé
Si l'objet Error est créé par nous-mêmes, alors error.message est contrôlé par nous. Fondamentalement, quoi que nous mettions dans error.message, le premier paramètre (message) de window.onerror le sera. (Le navigateur apportera en fait de légères modifications, comme l'ajout du préfixe « Erreur non détectée : ».) Par conséquent, nous pouvons sérialiser les propriétés qui nous intéressent (telles que JSON.Stringify) et les stocker dans error.message, puis les lire. dans window.onerror Retirez-le et désérialisez-le. Bien entendu, cela se limite aux objets Error que nous créons nous-mêmes.
Le cinquième paramètre
Les fabricants de navigateurs connaissent également les limitations auxquelles tout le monde est confronté lors de l'utilisation de window.onerror, ils ont donc commencé à ajouter de nouveaux paramètres à window.onerror. Considérant que seul le numéro de ligne mais aucun numéro de colonne ne semble pas très symétrique, IE ajoute d'abord le numéro de colonne et le met dans le quatrième paramètre. Cependant, tout le monde se soucie davantage de savoir s'ils peuvent obtenir la pile complète, donc Firefox a déclaré qu'il serait préférable de mettre la pile dans le cinquième paramètre. Mais Chrome a déclaré qu'il est préférable de placer l'intégralité de l'objet Error dans le cinquième paramètre. Vous pouvez lire toutes les propriétés de votre choix, y compris les propriétés personnalisées. En conséquence, Chrome a évolué plus rapidement et a implémenté une nouvelle signature window.onerror dans Chrome 30, ce qui a conduit à la rédaction du projet standard en conséquence.
window.onerror = function(
errorMessage,
scriptURI,
lineNumber,
columnNumber,
erreur
) {
if (erreur) {
reportError(erreur
} else { reportError( {
message : errorMessage,
script : scriptURI,
line : lineNumber,
colonne : columnNumber
}); >
Régularisation des attributs
Les noms des attributs de l'objet Error dont nous avons parlé précédemment sont basés sur la méthode de dénomination de Chrome. Cependant, différents navigateurs nomment les attributs de l'objet Error de différentes manières, comme les adresses des fichiers de script dans Chrome. cela s'appelle script mais dans Firefox cela s'appelle nom de fichier. Par conséquent, nous avons également besoin d'une fonction spéciale pour normaliser l'objet Error, c'est-à-dire pour mapper différents noms d'attributs vers des noms d'attributs unifiés. Pour des méthodes spécifiques, veuillez vous référer à cet article. Même si les implémentations des navigateurs seront mises à jour, la maintenance manuelle d’une telle table de mappage n’est pas trop difficile.
Similaire au format d'une trace de pile. Cet attribut enregistre une pile d'informations sur les exceptions sous forme de texte brut. Étant donné que le format de texte utilisé par chaque navigateur est différent, il est également nécessaire de maintenir manuellement une expression régulière pour extraire la fonction de chaque cadre du texte brut. identifiant), fichier (script), numéro de ligne (ligne) et numéro de colonne (colonne).
Restrictions de sécurité
Si vous avez également rencontré une erreur avec le message « Erreur de script. », vous comprendrez de quoi je parle. Il s'agit en fait de la réponse du navigateur aux différentes limites des fichiers de script d'origine. La raison de cette restriction de sécurité est la suivante : en supposant que le HTML renvoyé par une banque en ligne après la connexion d'un utilisateur est différent du HTML vu par les utilisateurs anonymes, un site Web tiers peut insérer l'URI de la banque en ligne dans le script. attribut src. Bien entendu, HTML ne peut pas être analysé comme JS, le navigateur lancera donc une exception et le site Web tiers pourra déterminer si l'utilisateur est connecté en analysant l'emplacement de l'exception. Pour cette raison, le navigateur filtre toutes les exceptions levées par les fichiers de script provenant de différentes sources jusqu'à ce qu'il ne reste qu'un seul message inchangé tel que « Erreur de script » et que tous les autres attributs disparaissent.
Pour les sites Web d'une certaine envergure, il est normal que les fichiers scripts soient placés sur un CDN avec des sources différentes. Désormais, même si vous créez votre propre petit site Web, des frameworks courants tels que jQuery et Backbone peuvent directement référencer les versions sur les CDN publics pour accélérer les téléchargements des utilisateurs. Cette restriction de sécurité pose donc quelques problèmes, ce qui fait que les informations d'exception que nous collectons auprès de Chrome et Firefox sont des « erreurs de script » inutiles.
CORS
Pour contourner cette restriction, assurez-vous simplement que le fichier script et la page elle-même ont la même origine. Mais mettre le fichier script sur un serveur qui n'est pas accéléré par CDN ne ralentira pas la vitesse de téléchargement de l'utilisateur ? Une solution consiste à continuer à placer le fichier de script sur le CDN, à utiliser XMLHttpRequest pour télécharger le contenu via CORS, puis à créer une balise <script> Le code intégré dans la page provient bien entendu de la même source. <br><br>Cela semble simple, mais il y a de nombreux détails à mettre en œuvre. Utilisons un exemple simple : <br><div class="codetitle">
<span><a style="CURSOR: pointer" data="8772" class="copybut" id="copybut8772" onclick="doCopy('code8772')"><u>Copier le code </u></a></span> Le code est le suivant : </div>
<div class="codebody" id="code8772"> <br><script src ="http://cdn.com/step1.js"></script>
<script> ; <br><script src="http://cdn.com/step3.js"></script>
Nous connaissons tous cette étape 1, étape 2, étape 3 s'il y en a dépendances Si tel est le cas, vous devez suivre strictement cet ordre, sinon des erreurs peuvent survenir. Le navigateur peut demander les fichiers de step1 et step3 en parallèle, mais l'ordre est garanti lors de l'exécution. Si nous obtenons nous-mêmes le contenu des fichiers des étapes 1 et 3 via XMLHttpRequest, nous devons nous assurer de l'exactitude de la commande. De plus, n'oubliez pas que l'étape 2 peut être exécutée lorsque l'étape 1 est téléchargée de manière non bloquante, il faut donc également intervenir manuellement dans l'étape 2 pour la laisser attendre la fin de l'étape 1 avant de l'exécuter.
Si nous disposons déjà d'un ensemble d'outils pour générer des balises <script> pour différentes pages du site Web, nous devons ajuster cet ensemble d'outils pour apporter des modifications aux balises <script> <br><br><br><div class="codetitle">Copier le code<span><a style="CURSOR: pointer" data="91019" class="copybut" id="copybut91019" onclick="doCopy('code91019')"><u> Le code est le suivant :</u></a> </span><script> </div>scheduleRemoteScript('http: //cdn.com/step1.js'); <div class="codebody" id="code91019"></script>
<script> <br>scheduleInlineScript(function code() { <br>(function step2() {})() ; <br> }); <br></script>
<script> <br>scheduleRemoteScript('http://cdn.com/step3.js'); <br><br><br>Nous devons implémenter les deux fonctions planningRemoteScript et planningInlineScript, et nous assurer qu'elles sont définies avant la première balise <script> qui fait référence au fichier de script externe, puis les balises <script> formulaire. Notez que la fonction step2 initialement exécutée immédiatement a été placée dans une fonction de code plus grande. La fonction code ne sera pas exécutée, c'est juste un conteneur, afin que le code original de l'étape 2 puisse être conservé sans s'échapper, mais ne sera pas exécuté immédiatement. <br><br>Ensuite, nous devons implémenter un mécanisme complet pour garantir que le contenu du fichier téléchargé par planningRemoteScript en fonction de l'adresse et du code directement obtenu par planningInlineScript peut être exécuté l'un après l'autre dans le bon ordre. Je ne donnerai pas le code détaillé ici. Si vous êtes intéressé, vous pouvez l'implémenter vous-même. <br>Vérification inversée du numéro de ligne <br><br>Obtenir du contenu via CORS puis injecter du code dans la page peut briser les restrictions de sécurité, mais cela introduira un nouveau problème, à savoir un conflit de numéro de ligne. À l'origine, error.script pouvait être utilisé pour localiser le fichier de script unique, et error.line pouvait être utilisé pour localiser le numéro de ligne unique. Désormais, comme il s'agit de codes intégrés dans la page, plusieurs balises <script> ne peuvent pas être distinguées par error.script. Cependant, le numéro de ligne à l'intérieur de chaque balise <script> être utilisé pour localiser l’emplacement du code source où se trouve l’erreur. <br><br>Afin d'éviter les conflits de numéros de ligne, nous pouvons gaspiller certains numéros de ligne afin que les plages de numéros de ligne utilisées par le code réel dans chaque balise <script> Par exemple, en supposant que le code réel de chaque balise <script> ne dépasse pas 1 000 lignes, je peux alors laisser le code de la première balise <script> occuper les lignes 1 à 1 000 et laisser la seconde. La balise <script> occupe les lignes 1 001 à 2 000 (précédées de 1 000 lignes vides), et le code de la troisième balise <script> occupe les lignes 2001 à 3 000 (précédées de 2 000 lignes vides), et ainsi de suite. Ensuite, nous utilisons les attributs data-* pour enregistrer ces informations afin de les récupérer facilement. <br><div class="codetitle">
<span><a style="CURSOR: pointer" data="17722" class="copybut" id="copybut17722" onclick="doCopy('code17722')"><u>Copier le code</u></a></span> Le code est le suivant :</div>
<div class="codebody" id="code17722"> <br><script <BR>data-src ="http ://cdn.com/step1.js" <BR>data-line-start="1" <BR>> <br>// code pour l'étape 1 <br></script> > >data-src="http://cdn.com/step3.js"
data-line-start="2001"
>
// 'n' * 2000
// code pour l'étape 3
Après ce traitement, si la ligne d'erreur d'une erreur est 3005, cela signifie que le script d'erreur réel doit être 'http://cdn.com/step3.js', et la ligne d'erreur réelle est-elle devrait être 5. Nous pouvons effectuer cette vérification inverse du numéro de ligne dans la fonction reportError mentionnée précédemment.
Bien sûr, puisque nous ne pouvons pas garantir que chaque fichier de script ne contient que 1 000 lignes et que certains fichiers de script peuvent contenir nettement moins de 1 000 lignes, il n'est pas nécessaire d'attribuer une plage fixe de 1 000 lignes à chaque < script> Nous pouvons attribuer des intervalles en fonction du nombre réel de lignes de script, à condition que les intervalles utilisés par chaque balise
Tutoriels populaires
Plus>
Recommandations populaires
Derniers téléchargements
Plus>