portada debugging en angular

C贸mo gestionar errores de c贸digo en un proyecto de Angular

脷ltima actualizaci贸n:

Herramienta #1: Consola (developer tools) de chrome

Angular, a trav茅s de la consola de las dev tools de Chrome, se encarga de mandarnos mensajes de alerta cada vez que existe alg煤n tipo de error en nuestro c贸digo. Entender estos mensajes es vital para poder resolverlos. 

Error t铆pico n潞1

Supongamos que tenemos un proyecto b谩sico de Angular (con bootstrap incluido), donde s贸lo vamos a trabajar con el AppComponent. Nuestro archivo app.module.ts tiene este aspecto:

import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

El archivo app.component.html (la template del AppComponent) tiene este aspecto:

<div class="container"> <div class="row"> <div class="col-xs-12"> <h2>My Servers</h2> <button class="btn btn-primary" (click)="onAddServer()">Add Server</button> <br><br> <ul class="list-group"> <li class="list-group-item" *ngFor="let server of servers; let i = index">{{ server }}</li> </ul> </div> </div> </div>

Y el archivo app.component.ts tiene este aspecto:

import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { servers; onAddServer() { this.servers.push('Another Server'); } }

Y en el navegador, nuestra demo tiene esta pinta:

debugging en angular

Con esta configuraci贸n b谩sica, al pulsar el bot贸n "Add server" deber铆a a帽adirse un p谩rrafo con cada click con el mensaje que le hemos pasado en el archivo app.component.ts. Pero al pulsar, ver谩s que no ocurre nada. Si vas a a las dev tools (y te recomiendo que siempre las tengas abiertas cuando est茅s escribiendo c贸digo) ver谩s que tienes un bonito mensaje de error. 馃う鈥嶁檧锔

angular error por undefined

En tus dev tools el mensaje es m谩s largo, pero s贸lo he puesto la parte que nos interesa. Como ves, nos indica que el problema est谩 en el app.component.ts, concretamente nos dice que la propiedad sobre la que se aplica el m茅todo push no est谩 definida (aka undefined). Adem谩s, nos marca la l铆nea del c贸digo donde est谩 el problema (app.component.ts:12).  

Con esta informaci贸n, vamos al archivo app.component.ts a localizar el error. All铆 vemos que el m茅todo push est谩 aplicado sobre la propiedad servers, que est谩 declarada arriba, pero no definida. 隆AH脕! Aqu铆 estaba el problema. En typescript, es obligatorio definir las propiedades antes de usarlas. As铆 que simplemente definimos nuestra propiedad servers como un array vac铆o y problema solucionado 馃憦

keep calm & read devtools error
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { servers = []; onAddServer() { this.servers.push('Another Server'); } }

Ahora ya podemos hacer click en el bot贸n y el resultado ser谩 el esperado, y nuestras dev tools no nos mostrar谩n ning煤n error. 馃憤 馃檪

Herramienta #2: Sourcemaps

A veces puede ocurrirnos que ni siquiera tengamos un mensaje de error, y que a pesar de ello, nuestro c贸digo no se comporte como esper谩bamos. Para ver este tipo de errores, vamos a usar la demo anterior pero con el a帽adido de un m茅todo que elimine un elemento de la lista al hacer click sobre 茅l.

Este es el c贸digo del app.component.ts:

import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { servers = []; onAddServer() { this.servers.push('Another Server'); } onRemoveServer(id: number) { const position = id + 1; this.servers.splice(position, 1); } }

Y este el del template del AppComponent:

<div class="container"> <div class="row"> <div class="col-xs-12"> <h2>My Servers</h2> <button class="btn btn-primary" (click)="onAddServer()">Add Server</button> <br><br> <ul class="list-group"> <li class="list-group-item" *ngFor="let server of servers; let i = index;" (click)="onRemoveServer(i)">{{ server }}</li> </ul> </div> </div> </div>

Con esta configuraci贸n, ver谩s que puedes a帽adir tantos elementos como quieras a la lista, y al hacer click sobre ellos, se eliminan. Todos menos el 煤ltimo, y nosotros queremos que se elimine cualquier elemento al hacer click sobre 茅l. Entonces, 驴隆por qu茅 no funciona!? 馃樀

Lo que podemos hacer es comprobar en runtime por qu茅 nuestro c贸digo no funciona. 

1. En las dev tools vamos a la pesta帽a Sources y nos aseguramos de estar en Page en la barra lateral izquierda:

sourcemaps para debugging

Como ves, desde la pesta帽a Page podemos acceder a nuestra estructura de carpetas de nuestro proyecto de Angular. 

2. A帽adimos un breakpoint para que la ejecuci贸n de la funci贸n se pare justo ah铆. Cuando intentamos eliminar los 煤ltimos dos elementos de la lista, nos encontramos con esto:

sourcemaps para debugging

Nuestro debugger nos subraya en azul la l铆nea que se est谩 ejecutando. Ah铆 vemos que la position actual, la que intenta eliminar, es la correspondiente al elemento del array n煤mero dos. Pero, si hacemos hover sobre this.servers, ver谩s que en el array solo tenemos dos elementos, y dado que los arrays son 0-basedlos elementos tienen una posici贸n de 0 y 1. Pero la posici贸n 2 no existe, y por tanto, no puede ser eliminada. 馃槄

3. As铆 que vamos a hacer una peque帽a modificaci贸n de nuestro c贸digo para que funcione. 

  • Eliminamos el acceso al index del loop en el archivo app.component.html, porque no nos hace falta. 
  • Dejamos de pasarle un p谩rametro a la funci贸n onRemoveServer.
<div class="container"> <div class="row"> <div class="col-xs-12"> <h2>My Servers</h2> <button class="btn btn-primary" (click)="onAddServer()">Add Server</button> <br><br> <ul class="list-group"> <li class="list-group-item" *ngFor="let server of servers" (click)="onRemoveServer()">{{ server }}</li> </ul> </div> </div> </div>
  • Cambiamos el contenido de la funci贸n onRemoveServer por un simple m茅todo pop en el this.servers, y no le pasamos ning煤n par谩metro:
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { servers = []; onAddServer() { this.servers.push('Another Server'); } onRemoveServer() { this.servers.pop(); } }

隆Y problema solucionado! Ahora se pueden eliminar todos los elementos de la lista cuando se hace click en ellos. 馃槑 馃憦

Herramienta #3: Augury

Augury es una extensi贸n de google chrome, puedes conseguirla aqu铆. Al instalarla, quiz谩s tengas que reiniciar el navegador para poder verla. La encontrar谩s en las dev tools, en una pesta帽a en la misma l铆nea que Console, Source, etc.

 Esta herramienta dise帽ada especialmente para Angular nos permite tener una visi贸n global de nuestro proyecto de Angular desde el navegador. Puedes abrirla y explorarla, ver谩s que muestra cosas tan interesantes como las propiedades de cada componente, gr谩ficos de las dependencias, y muchas cosas m谩s, todas en un mismo sitio.

THE END!

隆Y con esto terminamos nuestro repaso a c贸mo gestionar errores en Angular! Espero que hayas aprendido algo nuevo 馃槉.  Si te queda alguna duda, 隆nos vemos en los comentarios!

Y si crees que este post puede serle 煤til a alguien, 隆comp谩rtelo!

Otros art铆culos que pueden interesarte

D铆as del 353 al 386
Objetivos versus realidad Y nuevamente, lleg贸 otro d铆a clave. Lleg贸鈥 pas贸. El pasado 4 de marzo este Reto Computer Geek[...]
Dates en JavaScript: Gu铆a completa
Introducci贸nLos dates son un tipo de objetos de JavaScript (JS), muy 煤tiles para trabajar con fechas, como podr铆a ser la fecha de[...]
D铆as del 2 al 4
"Si buscas resultados distintos no hagas siempre lo mismo" - Albert Einstein Estos d铆as estoy aprendiendo a hacer loops en[...]

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende c贸mo se procesan los datos de tus comentarios.

Como toda web legal que se precie, utilizamos cookies para asegurar que damos la mejor experiencia al usuario en nuestro sitio web. Si contin煤as utilizando este sitio asumiremos que est谩s de acuerdo. m谩s informaci贸n

Los ajustes de cookies de esta web est谩n configurados para "permitir cookies" y as铆 ofrecerte la mejor experiencia de navegaci贸n posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estar谩s dando tu consentimiento a esto.

Cerrar