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.
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.
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:
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 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:
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.
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.
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.