viernes, 30 de septiembre de 2011

Peticiones Ajax síncronas con jQuery

En la entrada pasada publiqué un código para asignar variables de sesión PHP desde jQuery con un POST enviado via Ajax. El código del script es el siguiente:

<script type="text/javascript">
  $(function() {
    $('.print_link').click(function() {
		var fixedurl = 'http://localhost/miapp/main/set_session_var';

		$.post( fixedurl,
		{ object_name: 'tmprow',
          id: $(this).attr('id'),
          monto: $(this).parent().parent().find('.monto').html()
		 },
			function(data){
			//donothing
		});

      return true;
    });
  });
</script>

Luego, en set_session_var (ya en PHP) se hacía el trabajo ordinario de asignar la variable de sesión. Hice la prueba con un ejemplo sencillo en que se tenían 2 vistas, test1 y test2, y cuando se hacía click a un enlace en test1 que llevaba a test2, se ejecutaba la función, justo antes de abandonar la página, de manera que ya en test2, "con suerte" se pudieran usar las variables recién asignadas.

He dicho "con suerte", porque, tratándose de Ajax y su asincronía, no tenemos la certeza de que cuando se cargue test2, ya las variables estén asignadas. El ejemplo mostrado era realmente sencillo, por lo que esto practicamente siempre se cumplía, pero luego comencé a hacer otras cosas en la función set_session_var, que hicieron que eventualmente, cuando cargara test2, aún no estaban mis variables de sesión.

¿La solución? Hacer el envío de forma síncrona, de manera que en el "return true;" garantice que ya se haya ejecutado el POST. Esto con $.post() de jQuery no se puede hacer, hay que utilizar $.ajax() directamente. Recordemos que $.post() es un atajo/simplificador de $.ajax para envío de POST asíncronos, el cual no permite especificar todas las opciones de $.ajax().

Bien, a $.ajax() podemos especificar la opción 'async' (que por omisión está en true, es decir, todo es enviado de forma asíncrona). Lo que tenemos que hacer es ponerla en false y ya. Es muy simple, en realidad. Dejo el código del script, sustituyendo el $.post() por $.ajax():

<script type="text/javascript">
  $(function() {
    $('.print_link').click(function() {
		var fixedurl = 'http://localhost/miapp/main/set_session_var';

		$.ajax({url: fixedurl,
		  type: 'POST',
		  async: false,
		  data: { object_name: 'tmprow',
           id: $(this).attr('id'),
           monto: $(this).parent().parent().find('.monto').html() }
		});
      return true;
    });
  });
</script>

4 comentarios:

Weena Jimenez dijo...

Excelente explicación, muchas gracias

Weena Jimenez dijo...
Este comentario ha sido eliminado por el autor.
Unknown dijo...

Manteca de la güena. Gracias

Miguel García dijo...

Una anotación, usar $.post con AJAX sincrono si es posible, solo debes ejecutar primero:

$.ajaxSetup({
async: false
});
De esa forma todas las llamadas $.post seran sincronas, pero despues debes usar esta instrucción para regresarlo:
$.ajaxSetup({
async: true
});

Mas información en el enlace:

https://robertomiguelz.blogspot.com/2016/06/ejecucion-de-ajax-en-forma-sincrona.html