Tabla de Contenidos

3.2 $http

El servicio $http permite hacer peticiones AJAX al servidor. Es realmente como el objeto XMLHttpRequest o el método ajax() de JQuery. La diferencia con estos dos últimos es que está integrado con Angular como un servicio (con todas las ventajas de ellos conlleva) pero principalmente porque notifica a AngularJS que ha habido un cambio en el modelo de JavaScript y actualiza la vista y el resto de dependencias adecuadamente.

Como en otros apartados de AngularJS es obligatorio usar las funciones de AngularJS como $http para que AngularJS sepa que se han modificado los datos.

Si quieres saber mas sobre JSON puede ir al tema 10.2 JSON Y si quieres saber sobre HTTP puede ir al tema http

Para explicar el servicio de $http vamos a seguir con nuestro ejemplo del seguro médico en el que vamos a obtener unos datos iniciales del seguro desde el servidor para mostrarlos en el formulario. Los datos se obtienen en formato JSON desde la url datos.json. Este fichero contendrá simplemente texto en formato JSON para que podamos obtener la información del servidor. Más adelante en el curso, obtendremos los datos mediante REST desde la base de datos , pero por ahora y para aprender a usar $http será simplemente un fichero estático.

El contenido del fichero datos.json es el siguiente:

{
    "nif":"12345678Z",    
    "nombre":"Carlos",
    "ape1":"Cano",
    "edad":41,
    "sexo":"H",
    "casado":true,
    "numHijos":3,
    "embarazada":false,
    "coberturas": {
      "oftalmologia":true,
      "dental":false,
      "fecundacionInVitro":false
    },
    "enfermedades":{
      "corazon":true,
      "estomacal":false,
      "rinyones":false,
      "alergia":true,
      "nombreAlergia":"Acaros"
    }
}

No está el campo “fechaCreacion” ya que las fechas son un tema complejo que trataremos más adelante.

La instancia

Lo primero que tenemos que hacer es obtener una referencia al servicio $http. Como ya hemos explicado en el tema anterior, tenemos que incluirlo como parámetro de nuestro controlador para que nos lo inyecte al crearlo.

var app=angular.module("app",[]);
   
app.controller("SeguroController",['$scope','$log','$http',function($scope,$log,$http) {

   
}]);

No hemos mostrado el resto de líneas del controlador para mejorar la legibilidad

config

$http acepta como parámetro un único objeto llamado config con todas las propiedades que necesita para la petición.

Veamos ahora alguna de las propiedades:

El objeto config contiene mas propiedades pero no vamos a explicarlas en este curso. Puedes ver la lista completa en $http Usage

Ahora vamos a hacer una llamada mediante GET a la URL datos.json y sin parámetros.

var app=angular.module("app",[]);
   
app.controller("SeguroController",['$scope','$log','$http',function($scope,$log,$http) {
  var config={
    method:"GET",
    url:"datos.json"
  }
   
}]);

No hemos mostrado el resto de líneas del controlador para mejorar la legibilidad

respuesta

Teniendo el objeto config ya podemos llamar al servicio $http. La llamada nos retornará un objeto response.

var app=angular.module("app",[]);
   
app.controller("SeguroController",['$scope','$log','$http',function($scope,$log,$http) {
  var config={
    method:"GET",
    url:"datos.json"
  }
  
  var response=$http(config);
   
}]);
No hemos mostrado el resto de líneas del controlador para mejorar la legibilidad

Realmente no nos responde con un objeto response sino con un objeto promise pero ya veremos más adelante en el curso los objetos promise.

Los datos

Si todo ha funcionado correctamente podremos obtener el objeto JavaScript correspondiente al String JSON que nos han pasado. Para ello llamaremos a la función success(fn) que acepta como único parámetro una función nuestra que será llamada cuando se obtengan los datos.

La función que le pasaremos tendrá 4 argumentos que son los siguientes:

Recuerda que headers no es un objeto con la cabeceras sino una función que permite obtener el valor de una cabecera.

var app=angular.module("app",[]);
   
app.controller("SeguroController",['$scope','$log','$http',function($scope,$log,$http) {
  var config={
    method:"GET",
    url:"datos.json"
  }
  
  var response=$http(config);
  
  response.success(function(data, status, headers, config) {
      $scope.seguro=data;
  });
   
}]);
No hemos mostrado el resto de líneas del controlador para mejorar la legibilidad

La línea 12 tiene mucha más importancia de la que parece, sólo que AngularJS nos lo hace todo muy sencillo. Como ya hemos dicho, el parámetro data contiene el objeto con los datos del servidor. Al asignárselo a la propiedad $scope.seguro modificamos nuestro modelo de datos por lo que automáticamente se modificarán los tag <input> de la página HTML ya que el formato del objeto es exactamente el mismo que el que tenemos en $scope.seguro.

El que se actualice automáticamente el modelo es lo que hace que tengamos que usar $http. Si hubiéramos usado directamente el objeto XMLHttpRequest o el método ajax() de JQuery , AngularJS no se habría enterado de los cambios y no se habría actualizado la página HTML.

Recuerda que la llamada a nuestra función de la línea 11 se hace de forma asíncrona tal y como se hacen las peticiones AJAX

El error

Si ocurre algún error, es decir si se retorna un 400, 500 ,etc, no se llamará a la función de success .Para poder controlar el error debemos llamar a una nuev función llamada error(fn) que al igual que success acepta como único parámetro una función la cual tiene los mismos argumentos que success.

No vamos a extendernos mas en esta función ya que funciona igual que success.

var app=angular.module("app",[]);
   
app.controller("SeguroController",['$scope','$log','$http',function($scope,$log,$http) {
  var config={
    method:"GET",
    url:"datos.json"
  }
  
  var response=$http(config);
  
  response.success(function(data, status, headers, config) {
      $scope.seguro=data;
  });
  
  response.error(function(data, status, headers, config) {
      alert("Ha fallado la petición. Estado HTTP:"+status);
  });
    
   
}]);
No hemos mostrado el resto de líneas del controlador para mejorar la legibilidad

Hacer un alert no es la mejor forma de tratar los errores pero a efectos de aprender lo vamos a poner así.

Uniendo todo el código

Ya hemos visto cómo funciona pero el código nos ha quedado un poco largo. Lo hemos hecho así para ir explicando todo poco a poco, pero vamos a condensarlo todo para que quede más corto y legible.

Un detalle a comentar antes es que las funciones success o error retornan el mismo objeto response , con lo que podemos concatenar las llamadas.

El código finalmente quedaría así:

var app=angular.module("app",[]);
   
app.controller("SeguroController",['$scope','$log','$http',function($scope,$log,$http) {

  $http({
    method: 'GET', 
    url: 'datos.json'
  }).success(function(data, status, headers, config) {
      $scope.seguro=data;
  }).error(function(data, status, headers, config) {
      alert("Ha fallado la petición. Estado HTTP:"+status);
  });
    
   
}]);
No hemos mostrado el resto de líneas del controlador para mejorar la legibilidad

Vemos cómo hemos puesto la configuración directamente en la llamada en vez de crear un objeto config. Hemos incluido la llamada a success tras llamar a $http sin crear una nueva variable response y finalmente como success retorna el mismo objeto que $htpp podemos a su vez llamar a error.

El poner en el controlador la llamada a $http es con fines educativos. Realmente debería estar dentro de un servicio y que dicho servicio se llamara desde el controlador.

El ejemplo correcto se explicará en 3.10 Ejemplo servicio

Ejemplo

Finalmente el controlador completo quedaría de la siguiente forma:

var app=angular.module("app",[]);
  
app.controller("SeguroController",['$scope','$log','$http',function($scope,$log,$http) {
  $scope.seguro={
    nif:"",
    nombre:"",
    ape1:"",
    edad:undefined,
    sexo:"",
    casado:false,
    numHijos:undefined,
    embarazada:false,
    coberturas: {
      oftalmologia:false,
      dental:false,
      fecundacionInVitro:false
    },
    enfermedades:{
      corazon:false,
      estomacal:false,
      rinyones:false,
      alergia:false,
      nombreAlergia:""
    },
    fechaCreacion:new Date()
  }
  
  $log.debug("Acabamos de crear el $scope");

  $http({
    method: 'GET', 
    url: 'datos.json'
  }).success(function(data, status, headers, config) {
      $scope.seguro=data;
  }).error(function(data, status, headers, config) {
      alert("Ha fallado la petición. Estado HTTP:"+status);
  });
  
}]);

Como ya hemos explicado hemos añadido en la línea 3 la referencia al objeto $http y hemos añadido en las líneas 30 a 37 la llamada a $http.

Referencias