Deb.js de kleinste foutopsporing ter wereld

Wij, als ontwikkelaars, schrijven code. Nu schrijven we niet alleen, we controleren ook of de geschreven code werkt. We spenderen veel tijd en doen er alles aan om ervoor te zorgen dat onze programma's doen wat ze moeten doen. Dit foutopsporingsproces is vaak pijnlijk. Vooral als we niet de juiste instrumenten gebruiken. Om dit probleem te helpen oplossen, introduceert het artikel van vandaag Deb.js, een kleine JavaScript-bibliotheek waarmee u vanuit de browser kunt debuggen.

Het voorbeeld

Laten we beginnen met het maken van een eenvoudige pagina met wat JavaScript-interactie. We zullen een formulier maken met twee velden en een knop. Zodra de gebruiker op de knop klikt, verzamelen we de gegevens en voeren een bericht uit in de console. Dit is de opmaak van de pagina:

Om het voorbeeld te vereenvoudigen, zullen we jQuery gebruiken voor de DOM-selectie en gebeurtenissen. We zullen de functionaliteit in de volgende module omwikkelen:

var Module = collectData: function (cb) var name = $ ('[name = "name"]'). val (); var adres = $ ('[naam = "adres"]'). val (); if (naam! = "&& address! =") cb (null, name: name, address: address);  else cb (msg: 'Ontbrekende gegevens'); , error: function (err) $ ('[data-element = "output"]'). html (err.msg); , success: function (data) $ ('[data-element = "output"]'). html ('Hello' + data.name + '!');  

De data verzamelen functie haalt de waarde uit de velden en controleert of de gebruiker iets heeft getypt. Als dit niet het geval is, wordt de callback gestart met een object dat een korte foutmelding bevat. Als alles in orde is, reageert het met nul als de eerste parameter en een ander object als de tweede, die de gegevens vasthoudt. De ontwikkelaar die de module gebruikt, moet controleren of er een foutbericht is doorgegeven. Zo niet, gebruik dan het tweede ontvangen argument. Bijvoorbeeld:

$ ('[value = "register"]'). on ('klik', functie () Module.collectData (functie (err, data) if (typeof err === 'object') Module.error ( err); else Module.success (data););); 

Dus, we controleren of het dwalen parameter is een object en zo ja, dan tonen we het bericht. Als we de code zorgvuldig bekijken, zullen we het probleem opmerken, maar laten we eens kijken hoe alles werkt:

Als er geen gegevens zijn, werkt ons script zoals verwacht. Er bestaat Ontbrekende gegevens tekst weergegeven onder het formulier. Als we echter iets toevoegen aan de velden en op de knop drukken, krijgen we een: Uncaught TypeError: kan 'msg' van null niet lezen, bericht. Laten we nu de bug opsporen en verwijderen.

De traditionele aanpak

Google Chrome heeft prachtige instrumenten om dergelijke problemen op te lossen. We kunnen op de weggegooide fout klikken en het stapeltracering zien. We zouden zelfs naar de exacte plek kunnen gaan waar de fout is veroorzaakt.

Het lijkt op de fout methode van onze module ontvangt iets dat is nul. En uiteraard, nul heeft geen eigenschap genaamd msg. Daarom gooit de browser de fout. Er is maar één plaats waar de fout functie wordt opgeroepen. Laten we een breekpunt invoegen en zien wat er gebeurt:

Het lijkt erop dat we het recht hebben gekregen gegevens object en fout is gelijk aan nul, wat het juiste gedrag is. Dus, het probleem zou ergens in de als clausule. Laten we er een toevoegen console.log en kijk of we in de goede richting gaan:

Module.collectData (functie (err, data) console.log (type van err); if (type van err === 'object') Module.error (err); else Module.success (data); ); 

En inderdaad, de type van err komt terug voorwerp. Daarom laten we altijd een foutmelding zien.

En voila, we hebben het probleem gevonden. We hoeven alleen maar de als verklaring voor als (err) en ons kleine experiment zal werken zoals verwacht.

Deze aanpak kan echter soms moeilijk zijn, dus houd rekening met de volgende tips:

  • Zoals we zagen, eindigden we met het loggen van een variabele. Het instellen van het breekpunt is dus niet altijd voldoende. We moeten ook naar de console springen. Tegelijkertijd moeten we naar onze code-editor en het Chrome-debugpaneel kijken. Dit zijn verschillende plekken om in te werken, die allebei vervelend kunnen zijn.
  • Het is ook een probleem als we veel gegevens hebben ingelogd op de console. Soms is het moeilijk om de benodigde informatie te achterhalen.
  • Deze aanpak helpt niet als we een prestatieprobleem hebben. Vaker wel dan niet, moeten we de uitvoeringstijd weten.

Het stoppen van het programma tijdens runtime en het controleren van de staat is onbetaalbaar, maar Chrome kan op geen enkele manier weten wat we willen zien. Zoals het zojuist in ons geval is gebeurd, moeten we het als clausule. Zou het niet beter zijn als we een tool direct toegankelijk hadden vanuit onze code? Een bibliotheek die vergelijkbare informatie bevat, zoals de debugger, maar die in de console leeft? Nou, Deb.js zou het antwoord op deze vraag kunnen zijn.

Deb.js gebruiken

Deb.js is een klein stukje JavaScript-code, 1,5 kilobytes geminimaliseerd, dat informatie naar de console verzendt. Het kan aan elke functie worden bevestigd en wordt afgedrukt:

  • De plaats en tijd voor de uitvoering van de functie
  • Stapel trace
  • Geformatteerde en gegroepeerde uitvoer

Laten we eens kijken hoe ons voorbeeld eruitziet, wanneer we Deb.js gebruiken:

We zien opnieuw de exact doorgegeven argumenten en het stacktracé. Merk echter de verandering in de console op. We werken aan onze code, ontdekken waar het probleem ligt en toevoegen .deb () na de definitie van de functie. Merk op dat het type van de dwalen is mooi in de functie geplaatst. Dus we hoeven er niet naar te zoeken. De uitvoer is ook gegroepeerd en geverfd. Elke functie die we willen debuggen, wordt in een andere kleur afgedrukt. Laten we nu onze fout oplossen en een andere plaatsen deb () om te zien hoe het eruit ziet.

Nu hebben we twee functies. We kunnen ze gemakkelijk van elkaar onderscheiden omdat ze in verschillende kleuren zijn. We zien hun invoer-, uitvoer- en uitvoeringstijd. Als er enige zijn console.log verklaringen, we zullen ze binnen de functies zien waar ze voorkomen. Er is zelfs een optie om een ​​beschrijving achter te laten voor een betere functieherkenning.

Merk op dat we hebben gebruikt debc en niet deb. Het is dezelfde functie, maar de uitvoer stort in. Als je Deb.js begint te gebruiken, zul je er snel achter komen dat je niet altijd alles wilt zien.

Hoe Deb.js is gemaakt

Het oorspronkelijke idee kwam van de blogpost van Remy Sharp over het vinden waar het console.log optreedt. Hij stelde voor dat we een nieuwe fout kunnen maken en de stacktracering vanaf daar kunnen krijgen:

['log', 'warn'] forElke (functie (methode) var oud = console [methode]; console [methode] = functie () var stack = (nieuwe fout ()). stack.split (/ \ n /); // Chrome bevat één regel "Error", FF niet. if (stack [0] .indexOf ('Error') === 0) stack = stack.slice (1); var args = [] .slice.apply (arguments) .concat ([stack [1] .trim ()]); return old.apply (console, args);;) 

De originele post is te vinden op Remy's blog. Dit is vooral handig als we ons ontwikkelen in een Node.js-omgeving.

Dus met het stack-trace in de hand moest ik op een of andere manier code in het begin en aan het einde van de functie injecteren. Dit is toen het patroon dat werd gebruikt in de berekende eigenschappen van Ember door mijn hoofd schoot. Het is een leuke manier om het origineel te patchen Function.prototype. Bijvoorbeeld:

Function.prototype.awesome = function () var original = this; return-functie () console.log ('before'); var args = Array.prototype.slice.call (argumenten, 0); var res = original.apply (this, args); console.log ( 'na'); return res;  var doSomething = function (value) retourwaarde * 2; .geweldig(); console.log (doSomething (42)); 

De deze sleutelwoord in onze patch, wijst naar de oorspronkelijke functie. We kunnen het later uitvoeren, wat precies is wat we nodig hadden, omdat we de tijd vóór en na de uitvoering konden volgen. Tegelijkertijd keren we onze eigen functie terug die als een proxy fungeert. We gebruikten .toepassen (dit, args) om de context en de doorgegeven argumenten te behouden. En gelukkig kunnen we Remy's tip ook een stacktracé krijgen.

De rest van de Deb.js-implementatie is slechts decoratie. Sommige browsers ondersteunen console.group en console.groupEnd wat veel helpt voor de visuele uitstraling van de logging. Chrome geeft ons zelfs de mogelijkheid om de afgedrukte informatie in verschillende kleuren te schilderen.

Samenvatting

Ik geloof in het gebruik van geweldige instrumenten en gereedschappen. De browsers zijn slimme instrumenten die zijn ontwikkeld door slimme mensen, maar soms hebben we meer nodig. Deb.js kwam als een klein hulpprogramma en heeft met succes een bijdrage geleverd aan het verbeteren van mijn debugging-workflow. Het is natuurlijk open source. Voel je vrij om problemen te melden of trekverzoeken te doen.

Bedankt voor het lezen.