Deb.js il più piccolo debugger del mondo

Noi, come sviluppatori, scriviamo il codice. Ora non stiamo solo scrivendo, stiamo anche controllando se il codice scritto funziona. Trascorriamo molto tempo e ci impegniamo molto, assicurando che i nostri programmi facciano ciò che dovrebbero fare. Questo processo di debug è spesso doloroso. Soprattutto se non stiamo usando gli strumenti adeguati. Per aiutare con questo problema, l'articolo di oggi introduce Deb.js, una piccola libreria JavaScript che ti aiuta a eseguire il debug all'interno del browser.

L'esempio

Iniziamo creando una semplice pagina con alcune interazioni JavaScript. Creeremo un modulo con due campi e un pulsante. Una volta che l'utente fa clic sul pulsante, raccoglieremo i dati e mostreremo un messaggio nella console. Ecco il markup della pagina:

Per semplificare l'esempio, utilizzeremo jQuery per la selezione e gli eventi del DOM. Concluderemo la funzionalità nel seguente modulo:

var Module = collectData: function (cb) var name = $ ('[nome = "nome"]'). val (); var address = $ ('[nome = "indirizzo"]'). val (); if (name! = "&& address! =") cb (null, nome: nome, indirizzo: indirizzo);  else cb (msg: 'Missing data'); , errore: function (err) $ ('[data-element = "output"]'). html (err.msg); , success: function (data) $ ('[data-element = "output"]'). html ('Hello' + data.name + '!');  

Il raccogliere dati la funzione ottiene il valore dai campi e controlla se l'utente ha digitato qualcosa. In caso contrario, attiva la richiamata con un oggetto contenente un breve messaggio di errore. Se tutto è OK, risponde con nullo come il primo parametro e un altro oggetto come il secondo, mantenendo i dati. Lo sviluppatore che utilizza il modulo, dovrebbe verificare se è passato un oggetto di errore. In caso contrario, quindi iniziare a utilizzare il secondo argomento ricevuto. Per esempio:

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

Quindi, controlliamo se il sbagliare parametro è un oggetto e se sì, mostriamo il messaggio. Se osserviamo attentamente il codice, individueremo il problema, ma controlliamo come funziona tutto:

Quando non ci sono dati, il nostro script funziona come previsto. C'è Dati mancanti testo visualizzato sotto il modulo. Tuttavia, se aggiungiamo qualcosa nei campi e premiamo il pulsante, otteniamo un: Uncaught TypeError: impossibile leggere la proprietà "msg" di null, Messaggio. Ora, cerchiamo il bug e lo rimuoviamo.

L'approccio tradizionale

Google Chrome ha strumenti meravigliosi per risolvere tali problemi. Potremmo cliccare sull'errore generato e vedere la sua traccia dello stack. Potremmo persino andare nel posto esatto in cui è stato prodotto l'errore.

Sembra il errore il metodo del nostro modulo riceve qualcosa che è nullo. E naturalmente, nullo non ha una proprietà chiamata msg. Ecco perché il browser genera l'errore. C'è solo un posto dove il errore la funzione è invocata. Mettiamo un breakpoint e vediamo cosa succede:

Sembra che abbiamo ricevuto il giusto dati oggetto e errore è uguale a nullo, qual è il comportamento corretto. Quindi, il problema dovrebbe essere da qualche parte nel Se clausola. Aggiungiamo a console.log e vediamo se stiamo andando nella giusta direzione:

Module.collectData (function (err, data) console.log (typeof err); if (typeof err === 'object') Module.error (err); else Module.success (data); ); 

E infatti, il typeof err ritorna oggetto. Ecco perché stiamo sempre mostrando un errore.

E voilà, abbiamo trovato il problema. Dobbiamo solo cambiare il Se dichiarazione a se (err) e il nostro piccolo esperimento funzionerà come previsto.

Tuttavia, a volte questo approccio può essere difficile, quindi prendi in considerazione i seguenti suggerimenti:

  • Come abbiamo visto, abbiamo finito con la registrazione di una variabile. Quindi, impostare il punto di interruzione non è sempre sufficiente. Dobbiamo anche saltare alla console. Allo stesso tempo, dobbiamo guardare il nostro editor di codice e il pannello di debug di Chrome. Questi sono diversi posti in cui lavorare, entrambi potrebbero essere fastidiosi.
  • È anche un problema se nella console sono registrati molti dati. A volte è difficile trovare le informazioni necessarie.
  • Questo approccio non aiuta se abbiamo un problema di prestazioni. Più spesso, dovremo conoscere il tempo di esecuzione.

Arrestare il programma in fase di esecuzione e controllarne lo stato non ha prezzo, ma Chrome non è in grado di sapere cosa vogliamo vedere. Come è successo nel nostro caso, dobbiamo ricontrollare il Se clausola. Non sarebbe meglio se avessimo uno strumento direttamente accessibile dal nostro codice? Una libreria che porta informazioni simili come il debugger, ma vive all'interno della console? Bene, Deb.js potrebbe essere la risposta a questa domanda.

Utilizzando Deb.js

Deb.js è un piccolo pezzo di codice JavaScript, 1.5 kilobyte minified, che invia informazioni alla console. Può essere collegato a ogni funzione e stampa:

  • La posizione e il tempo di esecuzione della funzione
  • Traccia dello stack
  • Output formattato e raggruppato

Vediamo come appare il nostro esempio, quando usiamo Deb.js:

Vediamo nuovamente gli argomenti passati esatti e la traccia dello stack. Tuttavia, notare la modifica nella console. Lavoriamo sul nostro codice, scopriamo dove può essere il problema e aggiungilo .deb () dopo la definizione della funzione. Si noti che il tipo di sbagliare è posizionato bene all'interno della funzione. Quindi, non dobbiamo cercarlo. Anche l'output è raggruppato e dipinto. Ogni funzione che vogliamo eseguire il debug verrà stampata con un colore diverso. Ora sistemiamo il nostro bug e ne posizioniamo un altro deb () per vedere come appare.

Ora abbiamo due funzioni. Potremmo facilmente distinguere tra loro perché sono in colori diversi. Vediamo i loro input, output e tempi di esecuzione. Se ce ne sono console.log dichiarazioni, li vedremo all'interno delle funzioni in cui si verificano. C'è anche un'opzione per lasciare una descrizione per un migliore riconoscimento delle funzioni.

Si noti che abbiamo usato debc e non debuttante. È la stessa funzione, ma l'output crolla. Se inizi a utilizzare Deb.js, scoprirai molto presto che non vuoi sempre vedere tutto.

Come è stato creato Deb.js

L'idea iniziale è arrivata dal post sul blog di Remy Sharp su come trovare dove console.log si verifica. Ha suggerito che possiamo creare un nuovo errore e ottenere la traccia dello stack da lì:

['log', 'warn']. forEach (function (method) var old = console [metodo]; console [metodo] = function () var stack = (nuovo errore ()). stack.split (/ \ n /); // Chrome include una sola riga "Errore", FF no. (stack [0] .indexOf ('Error') === 0) stack = stack.slice (1); var args = [] .slice.apply (argomenti) .concat ([stack [1] .trim ()]); return old.apply (console, args);;) 

Il post originale può essere trovato sul blog di Remy. Ciò è particolarmente utile se sviluppiamo in un ambiente Node.js.

Quindi, con la traccia dello stack in mano, in qualche modo avevo bisogno di iniettare il codice all'inizio e alla fine della funzione. Questo è quando il pattern usato nelle proprietà calcolate di Ember mi è saltato in testa. È un bel modo per correggere l'originale Function.prototype. Per esempio:

Function.prototype.awesome = function () var original = this; return function () console.log ('before'); var args = Array.prototype.slice.call (argomenti, 0); var res = original.apply (this, args); console.log ( 'dopo'); ritorno;  var doSomething = function (value) return value * 2; .eccezionale(); console.log (doSomething (42)); 

Il Questo parola chiave nella nostra patch, punta alla funzione originale. Potremmo eseguirlo più tardi, il che è esattamente ciò di cui avevamo bisogno, perché potevamo monitorare il tempo prima e dopo l'esecuzione. Allo stesso tempo, restituiamo la nostra funzione che funge da proxy. Abbiamo usato .applicare (questo, args) per mantenere il contesto e gli argomenti passati. E grazie al suggerimento di Remy, potremmo ottenere anche una traccia di stack.

Il resto dell'implementazione di Deb.js è solo decorazione. Alcuni browser supportano console.group e console.groupEnd che aiuta molto per l'aspetto visivo del logging. Chrome ci offre persino la possibilità di dipingere le informazioni stampate in diversi colori.

Sommario

Credo nell'uso di ottimi strumenti e strumenti. I browser sono strumenti intelligenti sviluppati da persone intelligenti, ma a volte abbiamo bisogno di qualcosa di più. Deb.js è venuto come una piccola utility e ha contribuito con successo ad aumentare il mio flusso di lavoro di debug. È, ovviamente, open source. Sentiti libero di segnalare problemi o fare richieste di pull.

Grazie per aver letto.