Introducción a Angular JS

Definición de Servicios para hacer Ajax Más videos

Descripción del tema

Hasta el momento hemos estado manejando la información sobre un arreglo de elementos en JavaScript, esto nos ha servidor para iterar, filtrar y desplegar la información en nuestras vistas, pero en la vida real estos casos no se dan muy a menudo, generalmente siempre tenemos un servidor con el cual nos comunicamos para enviar y recibir información.

En este tema veremos como conectarnos vía Ajax a un API en JSON para regresar el listado de categorías que hemos usado para filtrar los bookmarks.

Los servicios en Angular JS deben usarse para almacenar la lógica de persistencia, es decir, aquí es donde deberíamos realizar nuestras peticiones Ajax, hacer las peticiones REST, posiblemente hacer peticiones con JSONP, Websockets o cualquier otro método de comunicación para enviar y recibir información.

Algo muy importante a considerar es que los Servicios son objetos singleton, eso significa que solamente son creados una sola vez en toda nuestra aplicación, por el contrario los controladores son creados y eliminados cada que lo necesitemos, cuando nuestra aplicación comienza a crecer es muy recomendable tener varios controladores.

Ya que los controladores se destruyen cuando no so necesarios, muchas veces es buena idea utilizar los servicios para almacenar cierta información que requerimos utilizar en diferentes lugares de nuestra app. Los servicios también los podemos usar para compartir información entre los controladores, ya que podemos inyectar cualquier servicio en cualquier controlador de una manera muy sencilla.

Existen tres manera en Angular JS de crear servicios:

  1. Services (Servicios)
  2. Factories (Factorías)
  3. Providers (Proveedores)

En este tema nos enfocaremos en el primero de la lista. Para crear un servicio lo hacemos de la siguiente manera, el siguiente código lo agregamos en el archivo app.js.

.service('Category',function(){

})

Con eso estamos creando un servicio llamado Category, la función que se le esta pasando en el segundo parámetro será el constructor de la clase, ahí podemos agregarle métodos, propiedad y definir todo lo que necesitemos.

Para este ejemplo vamos a hacer una petición Ajax al API que nos regresará el listado de categorías disponibles de nuestra aplicación. Vamos a utilizar un servicio llamado $http, este servicio es parte del core de Angular.

.service('Category',function($http){ //Step 1

    this.getAll = function(success,failure){ //Step 2
        
    }
})
  1.  En el paso uno inyectamos el servicio $http, Angular automáticamente reconocerá el servicio adecuado y lo insertará a nuestra clase.
  2. En el segundo paso creamos la función getAll, esta función solicitará mediante una petición GET el listado de categorías disponibles. Como parámetros recibirá dos callbacks, el caso de éxito y el caso de error.

La inyección que Angular hace del servicio $http, se le denomina Dependency Injection, este es un concepto importante y es una de las características más populares de la librería. Para que funcione debemos nombrar al parámetro exactamente igual que el servicio a inyectar.

Una buena práctica al nombrar nuestros servicios es evitar poner el signo $ al inicio del nombre del servicio, ya que los servicios de Angular inician con este nombre y podríamos crear colisiones.

Ahora vamos a realizar la petición Ajax de la siguiente manera.

.service('Category',function($http){

    this.getAll = function(success,failure){
        $http.get('http://bookmarks-angular.herokuapp.com/api/categories') //Step 1
            .success(success) //Step 2
            .error(failure);  
    }
})
  1. En el paso uno utilizamos el método get, este método realizará una petición de tipo GET a la URL que se le pasa como parámetro.
  2. El método get regresa una promesa con dos métodos que usaremos, el success y el error, a los cuales les asignamos los callbacks que recibimos como parámetros. Estos métodos se ejecutarás solo si la petición se realizó exitosamente o no.

La URL del API que estamos accediendo, esta sobre heroku, así que si tarda un rato en responder la primera vez significa que nadie ha usado el API en un tiempo y heroku manda a dormir los servidores para ahorrar recursos. He configurado el servidor para recibir peticiones CORS, es por eso que la llamada Ajax nos funcionará sin problema.

Ya que tenemos nuestro servicio listo, vamos a usarlo en el controlador que ya tenemos.

.controller('MainController',function($scope,Category){ //Step 1
    $scope.name = 'Carl'

    Category.getAll(function(data){          //Step 2
        $scope.categories = data.categories; //Step 3
    });

    //...

});
  1. En el paso uno inyectamos nuestro servicio al controlador, para esto simplemente lo definimos como parámetro y angular lo insertará por nosotros. 
  2. En el paso dos invocamos el método getAll y le pasamos el callback de éxito, podríamos también pasarle el callback de error, pero por el momento así lo dejaremos.
  3. En el paso tres asignamos las categorías que recibimos en la respuesta de la petición Ajax a la propiedad en el scope que ya teníamos definida.

Lo último que debemos cambiar es el template, ya que ahora estamos recibiendo objetos y no solamente strings en el arreglo de categorías.

<!-- sidebar -->
<div class="column col-sm-3" id="sidebar">
    <p class="nav-title">
      Categories 
      <a href="#" class="pull-right"><i class="glyphicon glyphicon-folder-open"></i></a>
    </p>
    <ul class="nav">
        <li ng-repeat="category in categories" ng-class="{active: isCurrentCategory(category.name)}">
            <a href="#" ng-click="setCurrentCategory(category.name)"> <i class="glyphicon glyphicon-tags"></i> {{category.name}}</a>
        </li>
    </ul>
</div>
<!-- /sidebar -->

El template ahora usará la propiedad name de cada objeto, con esto nos aseguramos que todo se imprima de manera adecuada. Al probar nuestros cambios deberíamos ver algo como la siguiente imagen. 

Servicios en Angular JS

Servicios en Angular JS

Ahora estamos desplegando las categorías desde un API en JSON. Si todo ha salido bien la aplicación debe seguir funcionando adecuadamente.

En el siguiente tema veremos otra manera de crear servicios en Angular JS, además haremos peticiones REST al API para guardar, editar y borrar los bookmarks.

Si te ha gustado este tutorial me harías un gran favor si lo compartes en Twitter y Facebook. Recuerda que puedes descargar el código fuente, el video y ver la demostración de este tutorial.

Te gustaría recibir más tutoriales como este en tu correo?

Este tutorial pertenece al curso Introducción a Angular JS, te recomiendo revises el resto de los tutoriales ya que están en secuencia de menor a mayor complejidad.

Si deseas recibir más tutoriales como este en tu correo te recomiendo registrarte al curso, si ya eres miembro solo identifícate y registrate al curso, si no eres miembro te puedes registrar gratuitamente!

Si no gustas registrarte en este momento no es necesario! Aún así puedes recibir los nuevos tutoriales en tu correo! Jamás te enviaremos Spam y puedes cancelar tu suscripción en cualquier momento.

¿Olvidaste tu contraseña?

22Comentarios

  • Avatar-6 Jorge Armand Olivero 21/10/2014

    Excelente, gracias por tus conocimientos, una duda ¿Alguna persona recomienda usar mucho angular-resources, crees que es mejor hacer uso de está en vez de seguir usando la forma que explicaste?, ami me gusta mas la forma en que la explicaste, pero la verda no tengo claro cuales serian las ventajas de usar angular-resource?

    • Avatar-5 Crysfel Villa 21/10/2014

      Hola Jorge! Exactamente ese el tema que sigue, si todo sale como lo planeado el próximo jueves estaré publicando un tutorial sobre el uso del servicio $resource. Sobre cual usar depende de lo que necesites realizar, en este caso ya que no tenemos planeado crear categorías (eso planeo dejarlo de tarea xD) nos conviene usar un el $http para una sola URL aislada. Por el contrario, para los bookmarks, necesitamos crear, editar, borrar y listar. Todas esas operaciones las haremos mediante un servicio REST, para esos casos lo mejor es usar $resource como tu mencionas. Hablaré de esto mismo en el siguiente video, gracias por dejar tus dudas, eso me sirve para mejorar los próximos videos. Saludos

    • Avatar-10 Cesar Murillo 22/10/2014

      Primero que nada agraderte el tutorial es muy bueno. Ahora estas manejando todo en un solo archivo, desearia cual es tu la "Angular way" de separar controladores, rutas , servicios, filtros etc. Saludos

      • Avatar-3 Crysfel Villa 22/10/2014

        Hola Cesar, tengo planeado realizar un curso avanzado donde se hará una app más grande, creando varios controladores, rutas, etc. Este curso solamente es una introducción a Angular JS ;) Personalmente prefiero separar mis archivos en pequeños módulos reutilizables, en cada módulo definir los servicios, controllers, templates y rutas necesarias. Como te comentaba, ya estoy trabajando en el siguiente curso xD Saludos

      • Avatar-7 Osay 27/10/2014

        excelente curso espero la versión avanzada

        • Avatar-5 Julio Yacot 01/11/2014

          Hola, una pregunta: Ciertamente es muy útil implementar los Servicios con consultas Ajax, pero hasta donde entiendo estas se realizan una única vez al cargase la petición Seria posible realizar las consultas constatemente? algo así como un websocket? Gracias por el curso!

          • Avatar-10 Crysfel Villa 01/11/2014

            Es correcto, al final del día los servicios hace peticiones Ajax, si quisieras recibir notificaciones/mensajes del servidor es necesario utilizar websockets, yo utilizaba GoAngular pero cerraron el servicio hace como mes y medio :( aunque implementar los websockets es muy sencillo también xD Saludos

            • Avatar-4 Amador 12/11/2014

              hola, excelente el aporte que haces, quiero seguir con este curso pero podrias decirme como haces para obtener la api de heroku? es una app de que tipo? , o una base de datos, me quede en esa parte, de antemano gracias.

              • Avatar-11 Crysfel Villa 12/11/2014

                Hola Amador. Puedes apuntar directamente a esa URL en tu código, acepta peticiones CORS. La API esta hecha en Rails4, la base de datos que usa es PostgreSQL, creo que sería buena idea compartir el código también. Saludos

              • Avatar-6 Elvin Landeta 10/12/2014

                Buenas, me habia ausentado un poco de estos tutoriales debido a que ultimamente he tenido mas obligaciones de lo normal, Veo que continuan igual o mas Interesante. Solo tengo una interrogante. Puedo ver que tiene tanto el modulo, el servicios y el controlador en un mismo archivo. mi pregunta es ¿Podria tener cada uno de estos elementos en archivos separados? ¿De ser asi habria que hacer referencia a cada archivo de esto dentro de la Pagina HTML o vastaria con invocar al ultimo que contiene la Inyesion por dependencia?

                • Avatar-10 Crysfel Villa 10/12/2014

                  Hola Elvin, bienvenido nuevamente! Para separar las clases en diferentes archivos necesitarías importar cada archivo en el HTML, el "dependency injection" no lo hace, si quisieras hacerlo dinámico (en desarrollo) podrías usar Grunt o Gulp para estar revisando los cambios e incluyendo removiendo archivos de manera automática. Saludos

                • Avatar-4 carlos balam 27/04/2015

                  por ejemplo si quisiera traer una peticion ajax si almacenar esa informacion en el servicio pero sin ejecutarlo cada ves como una funcion sino traerlo desde una variable

                  • Avatar-4 carlos balam 27/04/2015

                    por ejemplo lo siguiente app.factory('whatever', function($http){ var _data = {}; $http.get('/usuario/general'). success(function(data,status,header,config){ _data = data; }); return _data; })

                    • Avatar-5 Crysfel Villa 05/05/2015

                      Te refieres a cachar la información localmente? Pues podrías condicionar la petición Ajax basado en si ya tienes la información, la sacas de la variable, el detalle es que tienes que usar promesas porque la primera vez que saques la información será una llamada asincrona, el resto ya no, pero la primera sí, entonces lo recomendable es usar promesas para evitar problemas. Saludos

                    • Avatar-11 Fernando Cabrera 03/07/2015

                      Me sale este error cuando referencio los servicios por angular Error: [ng:areq] http://errors.angularjs.org/1.4.1/ng/areq?p0=fn&p1=not%20a%20function%2C%20got%20undefined at Error (native) at file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/FrameWorkLibrary/Angular/angular.min.js:6:416 at Sb (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/FrameWorkLibrary/Angular/angular.min.js:21:401) at Qa (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/FrameWorkLibrary/Angular/angular.min.js:21:488) at Object.$get.g.error (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/FrameWorkLibrary/Angular/angular.min.js:86:423) at getAll (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/app.js:11:16) at new (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/app.js:18:18) at Object.e [as invoke] (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/FrameWorkLibrary/Angular/angular.min.js:39:19) at $get.Q.instance (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/FrameWorkLibrary/Angular/angular.min.js:80:122) at N (file:///C:/Users/FernandoWin7/Desktop/AngularCourse/js/FrameWorkLibrary/Angular/angular.min.js:61:181)

                      • Avatar-5 Juan Pablo Betancur 06/07/2015

                        Hola Fernando este error que te esta saliendo es debido al 'use strict' en tu archivo js, la solución es muy sencilla en tu controlador cuando llamas al metodo getAll de Category tienes que tambien hacer el callback del error. Intentalo de esta manera y veras como se soluciona el problema puesto que el error apunta a que falta un argumento a la función getAll en este caso sería el del error. Category.getAll(function(data) { $scope.categories = data.categories; }, function(data) { console.error(data); });

                        • Avatar-9 drxgou 02/12/2015

                          Muchas Gracias JUAN... con esa repuesta también me ayudaste

                          • Avatar-5 Miguel Angel Sanchez 26/04/2016

                            Gracias, también me fue de ayuda :)

                          • Avatar-10 arturo castañeda 22/11/2015

                            Hola muchas gracias por estos cursos, son los primeros que me funcionan después de tanto buscar. Despues de tanto pelear porque el angular que baje v 1.4 stable no me funcionaba opte por poner el angular que metes dentro del html y funcionó sin problemas, mis dudas son las siguientes: 1. ¿Por qué el angular no me funcionaba en la versión actual estable? 2. ¿Hay problemas entre versiones de angular? 3. ¿Que es lo recomendable en estos casos? Espero tu respuesta que me seria de mucha ayuda ya que soy nuevo en este framework. Gracias!

                            • Avatar-11 jhon javier 06/11/2016

                              Hola como les va.. tengo un problema, me toco crear el servicio de esta manera, pues me daba un error,, .service('CategoryService',function($http){ this.getAll = function(success,failure){ $http({ method: 'GET', url: 'http://bookmarks-angular.herokuapp.com/api/categories' }).then(function success(success){ console.log(success); }, function error(failure) { console.log(failure); }); } por consola si me esta regresando el json, pero en mi template no carga nada ... este s mi html <p class="nav-title"> Categories <a href="#" class="pull-right"><i class="glyphicon glyphicon-folder-open"></i></a> </p> <ul class="nav"> <li> <a href="#"> <i class="glyphicon glyphicon-tags"></i> {{category.name}}</a> </li> </ul> Estoy usando angular AngularJS v1.5.8 Gracias.

                              • Avatar-7 jhon javier 06/11/2016

                                ya lo solucione , gracias....

                              Instructor del curso

                              Crysfel3

                              Autor: Crysfel Villa

                              Ha participado en varios proyectos con Angular y es participante activo del grupo de Angular NYC.

                              Descarga Código Fuente Ver Demostración

                              Regístrate a este curso

                              Este tutorial pertenece al curso Introducción a Angular JS, revisa todos los tutoriales que tenemos en este mismo curso ya que están en secuencia y van de lo más sencillo a lo más complicado.

                              Tendrás acceso a descargar los videos, códigos y material adicional.

                              Podrás resolver los ejercicios incluidos en el curso así como los Quizzes.

                              Llevarás un registro de tu avance.