Estás en... Home > Programación > Notificador Ajax usando jQuery

Notificador Ajax usando jQuery

3

Publicado el 04/03/2010 en Programación por Jose M. Carbonell

Jose M. Carbonell

Ingeniero de sistemas y apasionado de Ruby on Rails, desarrollo web y metodologías ágiles. Uno de los primeros en utilizar Ruby on Rails Rails en España.

Una petición AJAX es una petición asincrona a un servidor, es decir, en segundo plano. De esta forma es posible actualizar los datos de una página sin necesidad de recargarla por completo. Con jQuery este tipo de peticiones se realiza básicamente con la función jQuery.ajax() o lo que es lo mismo $.ajax().

Cuando se realiza una petición Ajax el usuario no tiene un feedback claro como el que se recibe cuando se hace click en un enlace normal. No sabe por tanto que algo está ocurriendo hasta que ocurre. El problema es que el usuario puede pensar que no ha pinchado bien el enlace y reintentarlo mientras aún se está procesando la primera petición.

Es necesario, por tanto, que proporcionemos al usuario un indicador de que se está llevando a cabo algun tipo de acción.

Esto se puede hacer de diferentes maneras, ya sea cambiando el texto del enlace o desactivandolo, insertar algun tipo de spinner o mostrando un mensaje indicativo, etc., y esto deberemos hacerlo mismo en cada petición Ajax. La función mostrada previamente ($.ajax()) nos ofrece una forma de crear callbacks que nos permitirán realizar las acciones que nosotros queramos cuando se produzca algun tipo de evento relacionado con la petición AJAX. Estos eventos son tales como: inicio de la petición, petición satisfactoria, error en la petición, petición completada, etc..

Para mostrar el ejemplo vamos a hacer una simple petición Ajax para obtener los últimos 15 mensajes de estado de la cuenta de twitter de Theproc.es. Estos mensajes se obtendrán de forma asincrona al hacer click en un enlace y se mostrarán en la misma página sin necesidad de recargarla.

Aquí vamos a crear un notificador que se encargará de mostrar bajo el cursor del ratón un spinner para que el usuario sepa que algo está ocurriendo:

Notificador Ajax

Paso 1 - Petición AJAX

La URL para obtener los mensajes de estado en formato JSON es: http://api.twitter.com/status/user_timeline/theproc_es.json

La petición tendrá la siguiente forma:

$.ajax({
  url: "http://api.twitter.com/status/user_timeline/theproc_es.json?count=15&callback=?"
  dataType: 'json',
  success: function(data){
    // procesado de la respuesta
  }
});

El contenido de la función encargada de procesar la respuesta es el siguiente:

function(data){
  var list = $('<ul>')
  $(data).each(function(){
    $('#result').html("");
    $(data).each(function(){
      $('<div>').append("<div><strong>"+this.user.screen_name+":</strong> "+this.text+"</div>");
    });
  });
}

Paso 2 - Notificando la petición

La función $.ajax() permite el uso de callbacks, es decir, la funciones que se llamaran en determinados momentos de la petición. De hecho, en el ejemplo anterior ya hemos usado uno, el callback success que es el que se invoca cuando se reciben los datos correctamente.

Ahora los que nos interesan son ajaxStart y ajaxStop. Estos se producen, justo antes de enviar los datos al servidor y al final de la petición respectivamente.

El código anterior con los nuevos callbacks es el siguiente:

$('body').append(
  $('<div>').attr('id', 'loading').append(
      $('<img>').attr('src', 'ajax-loader.gif').attr('alt', 'Loading...')
    ).css({
      position: 'absolute',
      display: 'none'
    })
  );

$(document).mousemove(function(e){
  $('#loading').css({left: e.pageX + 10, top: e.pageY + 15});
}

$('#link').click(function(e){
  e.preventDefault();
  $.ajax({
    url: "http://api.twitter.com/status/user_timeline/theproc_es.json?count=15&callback=?"
    dataType: 'json',
    success: function(data){
      // procesado de la respuesta
    },
    beforeSend: function(){
      $('#loading').show();
    },
    complete: function(){
      $('#loading').hide();
    }
  });
});

Primero he añadido una imágen al final del body. Esta imagen tiene posición absoluta y está oculta.

A continuación he creado una función sobre el evento de movimiento del ratón. Cuando el ratón se mueva se modificará la posición de la imagen según la posición actual del ratón.

El siguiente paso ha sido crear las funciones sobre los callback beforeSend y complete encargados de mostrar la imagen y ocultarla respectivamente.

Paso 3 - Notificador global

El problema es que si quisieramos hacer otra petición Ajax tendríamos que volver a crear las funciones de callback.

Por ello puede ser conveniente aplicar las funciones de callback automáticamente a todas las peticiónes AJAX.

Las peticiones AJAX disponen de una serie de eventos, unos locales (como los que hemos usado hasta ahora) que se son propios a la petición AJAX y otros globales que son retrasmitidos a todos los elementos del DOM.

El evento ajaxStart se transmite si se inicia una petición ajax y no hay ninguna otra petición ajax ejecutandose. Por otro lado, ajaxStop se transmite cuando ya no hay más peticiones Ajax ejecutandose.

Al ser retransmitidos por todos los elementos del DOM podemos escucharlos en el elemento #loading directamente:

$('#loading').bind('ajaxStart', function(){
    $(this).show();
  }).bind('ajaxStop', function(){
    $(this).hide();
  });

Código final:

$(document).ready(function(){
  // Insertamos la imagen
  $('body').append(
    $('<div>').attr('id', 'loading').append(
        $('<img>').attr('src', 'ajax-loader.gif').attr('alt', 'Loading...')
      ).css({
        position: 'absolute',
        display: 'none'
      })
    );

  // Reposicionado de la imagen
  $(document).mousemove(function(e){
    $('#loading').css({left: e.pageX + 10, top: e.pageY + 15});
  }
 
  // Eventos globales
  $('#loading').bind('ajaxStart', function(){
      $(this).show();
    }).bind('ajaxStop', function(){
      $(this).hide();
    });


  // La petición Ajax
  $('#link').click(function(e){
    e.preventDefault();
    $.ajax({
      url: "http://api.twitter.com/status/user_timeline/theproc_es.json?count=15&callback=?"
      dataType: 'json',
      success: function(data){
        $(data).each(function(){
          $('#result').html("");
          $(data).each(function(){
            $('#result').append("<div><strong>"+this.user.screen_name+":</strong> "+this.text+"</div>");
          });
        });
      }
    });
  });

});

Demostración

Bookmark and Share Compartir

3 comentarios sobre "Notificador Ajax usando jQuery"

  • Escrito el 04/03/2010

    Muy bien! no es mejor al momento de insertar la imagen en el body hacer algo komo esto, $("body").append(''); y k diferencia hay si x ejemplo en el AJAX para mostrar y ocultar la imagen uso esto, $('#link').click(function(e){ e.preventDefault(); $(".spinner").append(donde caiga aki en este kaso al body); $.ajax({ url: "http://api.twitter.com/status/user_timeline/theproc_es.json?count=15&callback=?" dataType: 'json', success: function(data){ $(".spinner").fadeOut("fast",function(){ $(data).each(function(){ $('#result').html(""); $(data).each(function(){ $('#result').append(""+this.user.screen_name+": "+this.text+""); }); }); }); } }); });

  • Escrito el 04/03/2010

    Si kontestas me notifikas, sale,

  • Escrito el 05/03/2010

    Insertar el spinner en el body y eliminarlo tras la petición es otra opción, pero es más costosa en términos de rendimiento. Ten en cuenta que la inserción y el borrado de elementos en el DOM es más costosa que cambiar las propiedades CSS, en este caso display. Además, en tu código estas creando un spinner cada vez que el usuario hace click en el enlace y sólo lo eliminas si el resultado de la petición es correcta. En caso contrarió la próxima vez que hagas la petición tendrás 2 spinners en el body. Tendrás un efecto parecido si haces una petición antes de que termine la anterior. Cada click crea un spinner. De todas formas, si prefieres insertar y borrar el spinner en cada petición yo pondría ese código en las funciones de eventos globales.

Deja tu Comentario


Enviar comentario