¿Cómo hago que jQuery espere a que finalice una llamada Ajax antes de que vuelva?

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.

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 con gracia 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; } } }); }); 

Si no desea que la función $.ajax() regrese inmediatamente, establezca la opción async en 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; } } }); }); 

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

No estoy usando $.ajax pero las funciones $.post y $.get , así que si necesito esperar la respuesta, uso esto:

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

El objeto subyacente XMLHttpRequest (utilizado por jQuery para realizar la solicitud) admite la propiedad asincrónica. Establecerlo en falso . Me gusta

 async: false 

En lugar de establecer asincrónico en falso, que generalmente es un diseño incorrecto, es posible que desee considerar bloquear la interfaz de usuario mientras la operación está pendiente.

Esto se puede lograr muy bien 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 (ie 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(''); // 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) $(' 

con esto ahora puedes 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 IU se bloqueará hasta que regrese el comando ajax

ver jsfiddle

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

Por ejemplo, en lugar de devolver true , podrías hacer:

 window.location="appropriate page"; 

De esta forma, cuando se llama a la función de éxito, la página se redirecciona.

Esto debería funcionar si estás usando jquery ajax

async: false

 $(".my_link").click( function(){ $.ajax({ async: false, 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; } } }); });