jueves, 15 de diciembre de 2016

Angular 2. Entrega 12. Cliente REST e inyección de dependencias

Seguimos repitiendo parte de lo que se dijo en curso de Micael Gallego. En este caso hablamos de REST. Comencemos por pasos

1. La clase Http

El código para utilizar Http podría ser:

Http http = ...
http.get(url).subscribe(
  response => console.log(response.json()),
  error => console.error (error)
);


En este caso utilizamos el método get de la REST API.
No se utilizan promesas sino observables.
Hacemos uns subscribe al objeto que te devuelve el get.
Al método subscribe le pasamos 2 funciones:

  1. La que devuelve el resultado correcto response
  2. La que devuelve error.

La función response supone en este caso que recibinos un json. Si se devolviera otra cosa nos daría error.

Observamos que NO hay un new del objeto http. En un test es dificil reemplazar el objeto rest por uno "fake" o "mock" (simulador o sustituto), por eso no se hace el new


2. Inyección de dependencias.

Para hacer tests, viene en nuestra ayuda el inyector de dependencias. Si queremos utilizar un objeto externo, delegamos en el framework para que te pase el componente que solicitamos. La ventaja de esto es que el framework sabrá que estas en modo testing y te proporcionará una dependencia del modo test, que será distinta a la que te proporcionará en modo real.
Por tanto en un test, el objeto http sustituto (mock) hará lo que queramos sin hacer peticiones reales.

Lo que necesitamos para que se inyecte la dependencia es que le indiquemos al constructor como parámetro de construcción un tipo de objeto determinado. No olvidemos importar las dependencias (en este caso Http). En este caso temenos una función constructor que recibe un parámetro Http.

import {Component} from '@angular/core';
import { Http } from '@angular/http';

@Component{
  selector: 'app-root',
  templateUrl: './app.component,html'
)}

export class AppComponent {
  constructor (private http: Http) {}
  search(title:string) {
    ...
  )
}


Y como siempre hay que advertir al module también las dependencias que tenemos.

import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { HttpModule, JsonModule } from '@angular/http';

import {AppComponent } from './app.component';

@NgModule ({
  declarations: [AppComponent],
  imports: [BrowserModule, FormsModule, HttpModule, JsonModule],
  bootstrap: [appcomponent]
})
export class AppModule {}

Si se devolviera XML, en vez de json tendríamos que indicarlo también en las dependencias.


3. Ejemplo

Vamos a llamar a una API pública de REST que saca libros. Veamos el app.component.html

<h1>Google Books</h1>

<input #title type="text">

<button  (click)="search(title.value); title.value=''">
  Buscar
</button>

<p *ngFor="let book of books">{{book}}</p>

Aquí, le pasamos al método search. la información que contiene el input, y despues vaciamos el contenido del input. Después mostramos todos los libros encontrados.

Veamos el componente app.component.ts, que tiene todo el jugo

<import {Component} from '@angular/core';
<import {Http) from '@angular/http';

@Component {
  selector: 'app-root',
  templateUrl: 'app/app.component.html'
  
)}

export class AppComponet {
  
  private books: string[] = [];
  
  constructor (private http: Http) {}
  
  search(title: string) {

    this.books =  [];

    let url = "https://www.googleapis.com/books/v1/volumes?q=intitle:" + title;

    //Hacemos una petición GET.Con subscribe ya no hace falta utilizar promesas
    this.http.get(url).subscribe(

      // Cuando todo va bien
      response => (
         // descargamos en memoria sobre el objeto data el resultado de la petición
         let data = response.json();
         for (var i = 0; i < data.items.length; i++) {
            let bookTitle = data.items[i].volumeInfo.title;
            this.books.push(bookTitle);
         }
      )
      
      //Cuando ha salido mal la petición
      error => console.error(error)
    );  
  }
}

Al aparecer dentro del constructor el objeto http como private, entonces ya es un atributo de la clase y se puede hacer referencia al el como this.http


Para amanizar la espera, se podría incluir un spinner antes de hacer la petición get, y despues ocultarlo dentro del response.


4. Peticiones POST y PUT

Con un ejemplo se ve mejor. Observar que los métodos post y pu se diferencian respecto a get en que les pasamos a parte de la url ,  también los datos. En el app.component.ts metemos este código

let data = {....}; //datos en json o xml

//tambien se hubiera podido poner put en vez de post
this.http.post(url, data).subscribe (
  response => console.log(response),
  error=> console.error(error)
);





No hay comentarios :

Publicar un comentario