Ejecutar una petición AJAX después de que otra petición AJAX haya finalizado
Un archivo JS está haciendo una llamada ajax. Dentro del éxito de esta llamada ajax se realiza otra llamada AJAX. La segunda llamada verifica si el email ya ha sido registrado. Si ya ha sido registrado, la segunda llamada AJAX no recibe datos de retorno como se muestra en firebug y la consola de Chrome en este caso. Pero el mismo código funciona perfectamente en localhost mientras que el problema mencionado ocurre SOLO en el servidor online.
La página alojada está en http://twmobilefitness.com/signup/
. El problema ocurre cuando haces clic en el enlace 'Register Now' al final. Tienes que registrarte dos veces con la misma dirección de email si quieres que ocurra el problema.
JS:
$.ajax( {
url : base_url+"/wp-admin/admin-ajax.php",
type : 'GET',
cache : false,
data : 'action=check_user_name&'
+ Math.floor( ( Math.random() * 100 ) +1 )
+ '&user_name='+user_name,
success : function( result ) {
if ( parseInt( result ) == 0 ) {
$( ".result" ).html( '<span class="error">Nombre de usuario no disponible</span>' );
} else if ( parseInt( result ) == 1 ) {
$.ajax( {
url : base_url
+ "/wp-admin/admin-ajax.php",
type : 'GET',
cache : false,
data : 'action=check_email_used&'
+ Math.floor( ( Math.random() *100 ) +1 )
+ '&email=' + email,
success : function( result_email ) {
if ( parseInt( result_email ) == 0 ) {
$( ".result" ).html( '<span class="error">Email ya está en uso</span>' );
} else if ( parseInt( result_email ) == 1 ) {
$( ".result" ).html( '' );
$( ".signup_div" ).hide();
$( ".signup_emergency_contact" ).show();
}
}
} );
}
}
} );
functions.php
tiene
add_action('wp_ajax_check_user_name','check_user_name');
add_action('wp_ajax_nopriv_check_user_name','check_user_name');
add_action( 'wp_ajax_check_email_used','check_email_used' );
add_action( 'wp_ajax_nopriv_check_email_used','check_email_used' );
// Verificar nombre de usuario
function check_user_name() {
global $wpdb;
$user_name = trim( $_GET['user_name'] );
$MobTraining = new MobTraining();
$table =trim( "{$wpdb->prefix}users" );
$array_where['user_login'] = $user_name;
$sql_fetch = $MobTraining->fetch( $table, $array_where );
$row = $wpdb->get_results( $sql_fetch, ARRAY_A );
if ( sizeof( $row ) != 0 ) {
echo '0';
} else {
echo '1';
}
die();
}
// Verificar si el email está en uso
function check_email_used() {
global $wpdb;
$email = trim( $_GET['email'] );
$MobTraining = new MobTraining();
$table = trim( "{$wpdb->prefix}users" );
$array_where['user_email'] = $email;
$sql_fetch = "SELECT * FROM $table WHERE `user_email`='$email'";
$row = $wpdb->get_results( $sql_fetch, ARRAY_A );
if ( sizeof( $row ) != 0 ) {
echo '0';
} else {
echo '1';
}
die();
}
¿Cómo hacer que el código funcione en el servidor online?

Lo que estás experimentando (AJAX funciona localmente, pero no en el servidor) es un problema de retraso. Localmente todo funciona tan rápido que no puedes ver tu problema. En resumen, este es tu problema:
La devolución de llamada AJAX (A) se ejecuta > La devolución de llamada AJAX (B) no sabe que tiene que esperar a (A) > No puedes ver el problema en tu instalación local porque (A) termina demasiado rápido.
Así que necesitas encontrar una manera de decirle a tu Callback (B) que tiene que esperar a (A). Aquí te mostramos cómo:
Registrar scripts y mover datos de PHP a JS
Registra y encola tus datos de la manera correcta: envuélvelos en una función o método y engancha a wp_enqueue_scripts
(público/temas), login_enqueue_scripts
(contraseña/inicio de sesión/registro) o admin_enqueue_scripts
. Luego usa wp_localize_script()
para mover datos de PHP a JS y hacerlos accesibles allí.
add_action( 'admin_enqueue_scripts', 'wpse118772jsObject' );
function wpse118772jsObject()
{
$scriptHandle = 'custom-script-name';
// Debería dividirse en funciones o métodos separados
wp_register_script(
$scriptHandle,
plugins_url( __FILE__, 'tu/ruta' ),
array( 'jquery' ),
plugin_dir_path( __FILE__ ).'tu/ruta' ),
true
);
wp_enqueue_script( $scriptHandle );
wp_localize_script(
$scriptHandle,
'pluginObject',
array(
'ajaxURl' => admin_url( 'admin_ajax.php' ),
'custom' => array(
// datos personalizados aquí
),
),
);
}
Cómo usar jQuery AJAX de la manera correcta
Hay varias funciones que puedes usar: la función predeterminada $.ajax({});
o sus accesos directos $.post();
, $.getJSON();
, etc.
Así que puedes simplemente usar algo como lo siguiente - usando los métodos de objeto success/fail
.
( function( $, plugin ) {
"use strict";
$.ajax( {
url : plugin.ajaxURl,
data : {
// otros datos
},
// Asumimos que respondes con un wp_send_json_success/error() adecuado en el PHP Cb.
dataType : "json",
// Transformación de la solicitud posible aquí.
beforeSend : function( xhr ) {
// Ejemplo:
// xhr.overrideMimeType( 'application/json' );
},
// Los manejadores reales
success : function( data, textStatus, jqXHR ) {
// Maneja la transformación de datos o manipulación del DOM aquí.
},
error : function( jqXHR, textStatus, errorThrown ) {
// silencioso: Registra el error
console.info( errorThrown );
// ruidoso: Lanza Excepción
throw errorThrown;
}
} );
} )( jQuery, pluginObject || {} );
Si quieres profundizar más y hacer las cosas realmente bien, tendrás que usar encadenamiento de métodos. (Todavía hay margen para mejorar).
( function( $, plugin ) {
"use strict";
$.ajax( {
url : plugin.ajaxURl,
data : {
// otros datos
},
} )
.done( function( data ) {
// Maneja solo respuestas exitosas
} )
.fail( function( reason ) {
// Maneja solo errores
console.debug( reason );
} )
.always( function( data, textStatus, response ) {
// Si quieres separar cosas manualmente
// response se convierte en errorThrown/reason O jqXHR en caso de éxito
} )
.then( function( data, textStatus, response ) {
// En caso de que trabajes con un deferred.promise, usa este método
// De nuevo, tendrás que separar éxito/error manualmente
} );
} )( jQuery, pluginObject || {} );
Nota: Para mejores ejemplos del envoltorio alrededor de la devolución de llamada, echa un vistazo a commonjs o AMD y sus diferencias.
Esperando otras respuestas AJAX
La pregunta interesante - y más poderosa de todo el manejo AJAX de jQuery (y otras bibliotecas) - es cómo esperar hasta que A termine para luego iniciar B y su procesamiento. La respuesta es la carga "diferida" y las "promesas".
Agregaré un ejemplo rápido. Quizás deberías pensar en construir un objeto y separar cosas adjuntándolas via this.
al objeto, pero para un ejemplo lo siguiente debería ser suficiente:
Ejemplo (A) Esto es básicamente como lo hago. Tendrás que rellenar los detalles por tu cuenta.
( function( $, plugin ) {
"use strict";
$.when(
$.ajax( {
url : pluginURl,
data : { /* ... */ }
} )
.done( function( data ) {
// 2da llamada terminada
} )
.fail( function( reason ) {
console.info( reason );
} )
)
// De nuevo, podrías aprovechar .done() también. Ver documentación de jQuery.
.then(
// Éxito
function( response ) {
// Ha sido exitoso
// En caso de más de una solicitud, ambas tienen que ser exitosas
},
// Fallo
function( resons ) {
// Ha lanzado un error
// en caso de múltiples errores, lanza el primero
},
);
} )( jQuery, pluginObject || {} );
Ejemplo (B) Nunca lo intenté así, pero debería funcionar también. Más fácil de leer, pero me gustan más las promesas resueltas con $.when()
.
( function( $, plugin ) {
"use strict";
$.ajax( {
url : plugin.ajaxURl,
data : {
// otros datos
}
} )
.done( function( data ) {
// Maneja solo respuestas exitosas
} )
.fail( function( reason ) {
console.info( reason );
} )
// Promesa terminada:
.then( function( data ) {
$.ajax( {
url : pluginURl,
data : { /* ... */ }
} )
.done( function( data ) {
// 2da llamada terminada
} )
.fail( function( reason ) {
console.info( reason );
} );
} );
} )( jQuery, pluginObject || {} );
Si quieres profundizar aún más, lee la documentación sobre deferred
y then
.
async/ await
EDITADO Como esta respuesta recibe bastante atención a lo largo de los años y ya tiene 8 años, por favor mira el siguiente fragmento de código.
Ten en cuenta que async/await
todavía trabaja con Promesas. Es solo azúcar sintáctico. También ten en cuenta a qué se refiere this
cuando usas funciones abreviadas como se ve en handlerB()
.
Eso incluso funcionará con jQuery.
( function( $, plugin ) {
const handlerA = async function( plugin ) {
try {
let res = await $.ajax( {
url : plugin.ajaxURl,
data : { /* algunos datos */ }
} )
.done( function( data ) {
// Maneja solo respuestas exitosas
} )
.fail( function( reason ) {
console.error( reason );
} )
return res;
} catch ( err ) {
console.error( err )
}
}
const handlerB = async data => { /* otra solicitud AJAX */ }
// Ejecutar
// …esperar…
let $resultA = await handlerA( plugin )
// Ahora ejecutar B
let $resultB = await handlerB( $resultA )
// Hacer algo con $resultB
} )( jQuery, pluginObject || {} );

en realidad no estoy usando ningún plugin. Una simple llamada AJAX de WordPress. Respecto al problema de retraso del servidor - Firebug muestra que la solicitud AJAX se completó sin recibir datos. Déjame revisar tu respuesta más a fondo.

@IstiaqueAhmed La descripción anterior no está destinada a ser un plugin. Solo es la base para escribir tu propio plugin (o, en caso de que no te importe la separación de responsabilidades, tu propio tema).

Gracias, esto fue de gran ayuda en un proyecto reciente. Ya lo voté hace mucho tiempo ;-) También solo quería mencionar que los callbacks success
, error
, complete
están obsoletos desde entonces en favor de los callbacks de promesa mencionados en la respuesta.

@birgire Por favor [edita] la respuesta. Verifiqué y solo la primera parte está obsoleta ahora. Gracias de antemano y gracias por las amables palabras :)

@kaiser en los ejemplos 'Esperando otras respuestas AJAX' A y B, ¿dónde están exactamente las segundas llamadas AJAX? No veo una segunda llamada AJAX en el Ejemplo A.

Para ejecutar una solicitud AJAX después de finalizar otra solicitud AJAX, debes agregar la siguiente línea:
async: false,
Es decir, necesitas agregar async: false
en el método ajax como se muestra a continuación:
$.ajax( { url : base_url+"/wp-admin/admin-ajax.php", type : 'GET', async: false,
