2009-04-16 15 views
197

Tengo una función del lado del servidor que requiere iniciar sesión. Si el usuario está conectado, la función devolverá 1 en caso de éxito. De lo contrario, la función devolverá la página de inicio de sesión.¿Cómo hago que jQuery espere a que finalice una llamada Ajax antes de que vuelva?

Quiero llamar a la función usando Ajax y jQuery. Lo que hago es enviar la solicitud con un enlace normal, con una función de clic aplicada. Si el usuario no está conectado o la función falla, quiero que la llamada Ajax se devuelva verdadera, para que se active el href.

Sin embargo, cuando uso el siguiente código, la función sale antes de que se realice la llamada Ajax.

¿Cómo puedo redirigir al usuario elegantemente a la página de inicio de sesión?

$(".my_link").click(
    function(){ 
    $.ajax({ 
     url: $(this).attr('href'), 
     type: 'GET', 
     cache: false, 
     timeout: 30000, 
     error: function(){ 
      return true; 
     }, 
     success: function(msg){ 
      if (parseFloat(msg)){ 
       return false; 
      } else { 
       return true; 
      } 
     } 
    }); 
}); 
+1

Puede ser un hilo viejo, pero como @kofifus señala establecer un sync to false es un mal diseño y "no se procesarán los tiempos de espera, etc.". Podría intentar esta solución simplificada: https: // stackoverflow.com/a/11576418/6937841 – Shan

Respuesta

295

Si no desea que la función $.ajax() para volver de inmediato, establezca la opción async a false:

$(".my_link").click(
    function(){ 
    $.ajax({ 
     url: $(this).attr('href'), 
     type: 'GET', 
     async: false, 
     cache: false, 
     timeout: 30000, 
     error: function(){ 
      return true; 
     }, 
     success: function(msg){ 
      if (parseFloat(msg)){ 
       return false; 
      } else { 
       return true; 
      } 
     } 
    }); 
}); 

embargo, quiero señalar que esto sería contrario al punto de AJAX. Además, debe manejar la respuesta en las funciones error y success. Esas funciones solo se invocarán cuando se reciba la respuesta del servidor.

+1

Quieres decir falso :) Supongo? – veggerby

+0

¡Hah! Si gracias. – cgp

+9

Pasar las buenas prácticas, en mi opinión, no es juzgar, y es la marca de algunas de las mejores respuestas aquí en StackOverflow. – semperos

27

El objeto XMLHttpRequest subyacente (utilizado por jQuery para realizar la solicitud) admite la propiedad asincrónica . Configúrelo en falso. Al igual que

async: false 
9

Creo que las cosas serían más fáciles si el código de su función success para cargar la página apropiada en lugar de volver true o false.

Por ejemplo en vez de volver true que podría hacer:

window.location="appropriate page"; 

De esta forma cuando la función del éxito se llama la página se le redirecciona automáticamente.

30

No estoy usando $.ajax pero los $.post y $.get funciones, por lo que si tengo que esperar la respuesta, yo uso esto:

$.ajaxSetup({async: false}); 
$.get("..."); 
+0

Esto funciona para $ .getJSON() también ... lo cual tiene sentido –

17

En lugar de establecer asíncrono a falso que suele ser un mal diseño, se Es posible que desee considerar bloquear la IU mientras la operación está pendiente.

Esto puede ser muy bien logrado con jQuery promesas de la siguiente manera:

// same as $.ajax but settings can have a maskUI property 
// if settings.maskUI==true, the UI will be blocked while ajax in progress 
// if settings.maskUI is other than true, it's value will be used as the color value while bloking (i.e settings.maskUI='rgba(176,176,176,0.7)' 
// in addition an hourglass is displayed while ajax in progress 
function ajaxMaskUI(settings) { 
    function maskPageOn(color) { // color can be ie. 'rgba(176,176,176,0.7)' or 'transparent' 
     var div = $('#maskPageDiv'); 
     if (div.length === 0) { 
      $(document.body).append('<div id="maskPageDiv" style="position:fixed;width:100%;height:100%;left:0;top:0;display:none"></div>'); // create it 
      div = $('#maskPageDiv'); 
     } 
     if (div.length !== 0) { 
      div[0].style.zIndex = 2147483647; 
      div[0].style.backgroundColor=color; 
      div[0].style.display = 'inline'; 
     } 
    } 
    function maskPageOff() { 
     var div = $('#maskPageDiv'); 
     if (div.length !== 0) { 
      div[0].style.display = 'none'; 
      div[0].style.zIndex = 'auto'; 
     } 
    } 
    function hourglassOn() { 
     if ($('style:contains("html.hourGlass")').length < 1) $('<style>').text('html.hourGlass, html.hourGlass * { cursor: wait !important; }').appendTo('head'); 
     $('html').addClass('hourGlass'); 
    } 
    function hourglassOff() { 
     $('html').removeClass('hourGlass'); 
    } 

    if (settings.maskUI===true) settings.maskUI='transparent'; 

    if (!!settings.maskUI) { 
     maskPageOn(settings.maskUI); 
     hourglassOn(); 
    } 

    var dfd = new $.Deferred(); 
    $.ajax(settings) 
     .fail(function(jqXHR, textStatus, errorThrown) { 
      if (!!settings.maskUI) { 
       maskPageOff(); 
       hourglassOff(); 
      } 
      dfd.reject(jqXHR, textStatus, errorThrown); 
     }).done(function(data, textStatus, jqXHR) { 
      if (!!settings.maskUI) { 
       maskPageOff(); 
       hourglassOff(); 
      } 
      dfd.resolve(data, textStatus, jqXHR); 
     }); 

    return dfd.promise(); 
} 

con esto ahora que puede hacer:

ajaxMaskUI({ 
    url: url, 
    maskUI: true // or try for example 'rgba(176,176,176,0.7)' 
}).fail(function (jqXHR, textStatus, errorThrown) { 
    console.log('error ' + textStatus); 
}).done(function (data, textStatus, jqXHR) { 
    console.log('success ' + JSON.stringify(data)); 
}); 

Y la interfaz de usuario se bloqueará hasta que las ajax comando devuelve

ver jsfiddle

+0

El hecho de no establecer asincria en falso hace exactamente lo mismo excepto en una sola línea de código? – Vincent

+3

En absoluto. Establecer async en falso hace que la solicitud sea asíncrona, esto detiene el procesamiento hasta que retorna, lo cual es generalmente una mala práctica, por ejemplo no e se procesarán respiraderos, otras solicitudes de ajax, tiempos de espera, etc. También puede modificar el código anterior para bloquear solo parte de la UI mientras su ajax está procesando (es decir, la parte que afectará) – kofifus

Cuestiones relacionadas