Deb.js le plus petit débogueur du monde

En tant que développeurs, nous écrivons du code. Maintenant, nous ne faisons pas qu'écrire, nous vérifions également si le code écrit fonctionne. Nous passons beaucoup de temps et déployons beaucoup d’efforts pour veiller à ce que nos programmes fassent ce qu’ils sont censés faire. Ce processus de débogage est souvent douloureux. Surtout si nous n'utilisons pas les instruments appropriés. Pour résoudre ce problème, l'article d'aujourd'hui présente Deb.js, une petite bibliothèque JavaScript qui vous permet de déboguer à partir du navigateur..

L'exemple

Commençons par créer une page simple avec une interaction JavaScript. Nous allons créer un formulaire avec deux champs et un bouton. Une fois que l'utilisateur a cliqué sur le bouton, nous allons collecter les données et générer un message dans la console. Voici le balisage de la page:

Afin de simplifier cet exemple, nous utiliserons jQuery pour la sélection et les événements DOM. Nous allons envelopper la fonctionnalité dans le module suivant:

var Module = collectData: function (cb) var nom = $ ('[nom = "nom"]'). val (); var address = $ ('[nom = "adresse"]'). val (); if (nom! = "&& adresse! =") cb (null, nom: nom, adresse: adresse);  else cb (msg: 'Données manquantes'); , erreur: fonction (erreur) $ ('[élément de données = "sortie"] "). html (erreur.msg); , success: function (data) $ ('[data-element = "output"] "). html (' Hello '+ data.name +'! ');  

le collecter des données function récupère la valeur des champs et vérifie si l'utilisateur a tapé quelque chose. Sinon, le rappel est déclenché avec un objet contenant un court message d'erreur. Si tout va bien, il répond avec nul en tant que premier paramètre et un autre objet en tant que second, contenant les données. Le développeur qui utilise le module doit vérifier si un objet d'erreur est passé. Sinon, commencez à utiliser le deuxième argument reçu. Par exemple:

$ ('[valeur = "register"] "). on (' click ', function () Module.collectData (function (err, données) (typeof err ===' objet ') Module.error ( err); else Module.success (data););); 

Donc, nous vérifions si le se tromper paramètre est un objet et si oui, alors nous montrons le message. Si nous examinons attentivement le code, nous identifierons le problème, mais vérifions comment tout fonctionne:

Lorsqu'il n'y a pas de données, notre script fonctionne comme prévu. Il y a Données manquantes texte affiché sous le formulaire. Cependant, si nous ajoutons quelque chose dans les champs et que nous appuyons sur le bouton, nous obtenons un: Uncaught TypeError: impossible de lire la propriété 'msg' de null, message. Maintenant, traquons le bogue et supprimons-le.

L'approche traditionnelle

Google Chrome dispose de merveilleux instruments pour résoudre de tels problèmes. Nous pouvons cliquer sur l'erreur renvoyée et voir sa trace de pile. Nous pourrions même aller à l'endroit exact où l'erreur a été produite.

Il ressemble à la Erreur méthode de notre module reçoit quelque chose qui est nul. Et bien sur, nul n'a pas de propriété appelée msg. C'est pourquoi le navigateur lève l'erreur. Il n'y a qu'un seul endroit où le Erreur la fonction est appelée. Mettons un point d'arrêt et voyons ce qui se passe:

On dirait que nous avons reçu le droit Les données objet et Erreur est égal à nul, quel est le comportement correct. Donc, le problème devrait être quelque part dans le si clause. Ajoutons un console.log et voir si nous allons dans la bonne direction:

Module.collectData (fonction (err, data) console.log (typeof err); if (typeof err === 'objet') Module.error (err); else Module.success (données); ) 

Et en effet, le typeof err résultats objet. C'est pourquoi nous montrons toujours une erreur.

Et voila, nous avons trouvé le problème. Nous devons juste changer le si déclaration à si (err) et notre petite expérience fonctionnera comme prévu.

Cependant, cette approche peut être parfois difficile, alors tenez compte des indications suivantes:

  • Comme nous l'avons vu, nous avons fini par enregistrer une variable. Donc, définir le point d'arrêt n'est pas toujours suffisant. Nous devons aussi sauter à la console. Dans le même temps, nous devons examiner notre éditeur de code et le panneau de débogage de Chrome. Ce sont plusieurs endroits différents où travailler, ce qui pourrait être ennuyeux..
  • C'est également un problème si nous avons beaucoup de données connectées à la console. Parfois, il est difficile de trouver les informations nécessaires.
  • Cette approche n'aide pas si nous avons un problème de performance. Plus souvent qu'autrement, nous aurons besoin de connaître le temps d'exécution.

Arrêter le programme à l'exécution et vérifier son état n'a pas de prix, mais Chrome n'a aucun moyen de savoir ce que nous voulons voir. Comme cela est arrivé dans notre cas, nous devons revérifier la si clause. Ne serait-il pas préférable d'avoir un outil directement accessible depuis notre code? Une bibliothèque qui apporte des informations similaires à celles du débogueur, mais vit à l'intérieur de la console? Deb.js pourrait bien être la réponse à cette question.

Utiliser Deb.js

Deb.js est un minuscule morceau de code JavaScript, de 1,5 kilo-octet au minimum, qui envoie des informations à la console. Il pourrait être attaché à chaque fonction et imprimer:

  • Lieu et heure d'exécution de la fonction
  • Trace de la pile
  • Sortie formatée et groupée

Voyons à quoi ressemble notre exemple lorsque nous utilisons Deb.js:

Nous voyons à nouveau les arguments passés exacts et la trace de la pile. Cependant, notez le changement dans la console. Nous travaillons sur notre code, découvrons où le problème peut être et ajoutons .deb () après la définition de la fonction. Notez que le type de se tromper est bien placé dans la fonction. Donc, nous n'avons pas à le chercher. La sortie est également regroupée et peinte. Chaque fonction que nous voulons déboguer sera imprimée avec une couleur différente. Réglons maintenant notre bug et plaçons un autre deb () pour voir à quoi ça ressemble.

Nous avons maintenant deux fonctions. Nous pourrions facilement les distinguer car ils sont de couleurs différentes. Nous voyons leurs temps d'entrée, de sortie et d'exécution. S'il y en a console.log déclarations, nous les verrons dans les fonctions où elles se produisent. Il y a même une option pour laisser une description pour une meilleure reconnaissance des fonctions.

Notez que nous avons utilisé debc et pas deb. C'est la même fonction, mais la sortie s'effondre. Si vous commencez à utiliser Deb.js, vous découvrirez très vite que vous ne voulez pas toujours tout voir..

Comment Deb.js a été créé

L’idée initiale est venue du billet de blogue de Remy Sharp sur la recherche du lieu où console.log se produit. Il a suggéré que nous puissions créer une nouvelle erreur et obtenir la trace de pile à partir de là:

['log', 'warn']. forEach (fonction (méthode) var ancien = console [méthode]; console [méthode] = fonction () var pile = (nouvelle erreur ()). pile.split (/ \ n /); // Chrome ne comporte qu'une seule ligne "Erreur", pas le FF. if (stack [0] .indexOf ('Error') === 0) stack = stack.slice (1); var args = [] .slice.apply (arguments) .concat ([pile [1] .trim ()]); retourne old.apply (console, arguments);;) 

Le message original peut être trouvé sur le blog de Remy. Ceci est particulièrement utile si nous développons dans un environnement Node.js.

Donc, avec la trace de la pile dans la main, j'avais besoin d'injecter du code au début et à la fin de la fonction. C'est à ce moment que le motif utilisé dans les propriétés calculées d'Ember est apparu dans ma tête. C'est un bon moyen de corriger l'original Fonction.prototype. Par exemple:

Function.prototype.awesome = function () var original = ceci; return function () console.log ('avant'); var args = Array.prototype.slice.call (arguments, 0); var res = original.apply (this, args); console.log ('après'); retourne res;  var doQuelque chose = fonction (valeur) valeur de retour * 2; .impressionnant(); console.log (quelque chose (42)); 

le ce mot-clé dans notre patch, pointe vers la fonction d'origine. Nous pourrions l'exécuter plus tard, ce qui est exactement ce dont nous avions besoin, car nous pouvions suivre le temps avant et après l'exécution. En même temps, nous renvoyons notre propre fonction qui agit en tant que proxy. Nous avons utilisé .appliquer (this, args) afin de conserver le contexte et les arguments passés. Et heureusement pour le conseil de Remy, nous pouvons aussi obtenir une trace de pile.

Le reste de l’implémentation Deb.js n’est que décoration. Certains navigateurs prennent en charge console.group et console.groupEnd ce qui aide beaucoup pour l'aspect visuel de la journalisation. Le chrome nous donne même la possibilité de peindre les informations imprimées en différentes couleurs.

Résumé

Je crois en l'utilisation d'excellents instruments et outils. Les navigateurs sont des instruments intelligents développés par des personnes intelligentes, mais nous avons parfois besoin de quelque chose de plus. Deb.js est venu comme un utilitaire minuscule et a contribué avec succès à stimuler mon flux de travail de débogage. C'est, bien sûr, open source. N'hésitez pas à signaler des problèmes ou à faire des demandes de tirage.

Merci d'avoir lu.