Eseguire una richiesta AJAX dopo che un'altra richiesta AJAX è terminata
Un file JS sta effettuando una chiamata ajax. All'interno del success di questa chiamata ajax viene effettuata un'altra chiamata AJAX. La seconda chiamata verifica se l'email è già stata registrata. Se è già registrata, la seconda chiamata AJAX non riceve dati di ritorno come mostrato in firebug e nella console Chrome. Tuttavia, lo stesso codice funziona correttamente in localhost mentre il problema menzionato si verifica SOLO sul server online.
La pagina ospitata si trova su http://twmobilefitness.com/signup/
. Il problema si verifica quando si fa clic sul link 'Register Now' alla fine. È necessario registrarsi due volte con lo stesso indirizzo email per far verificare il 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">Nome utente non disponibile </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 già utilizzata </span>' );
} else if ( parseInt( result_email ) == 1 ) {
$( ".result" ).html( '' );
$( ".signup_div" ).hide();
$( ".signup_emergency_contact" ).show();
}
}
} );
}
}
} );
functions.php
contiene
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' );
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();
}
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();
}
Come far funzionare il codice sul server online?

Quello che stai riscontrando (AJAX funziona localmente, ma non sul server) è un problema di ritardo. Localmente tutto funziona così velocemente che non riesci a vedere il problema. In breve, questo è il tuo problema:
Callback AJAX (A) viene eseguito > Callback AJAX (B) non sa che deve aspettare (A) > Non riesci a vedere il problema nella tua installazione locale perché (A) termina troppo velocemente.
Quindi devi trovare un modo per dire al tuo Callback (B) che deve aspettare (A). Ecco come:
Registrare script e spostare dati da PHP a JS
Registra e accoda i tuoi script e localizza i dati nel modo corretto: incapsula tutto in una funzione o metodo e aggancialo a wp_enqueue_scripts
(pubblico/temi), login_enqueue_scripts
(password/login/registrazione) o admin_enqueue_scripts
. Poi usa wp_localize_script()
per spostare i dati da PHP a JS e renderli accessibili lì.
add_action( 'admin_enqueue_scripts', 'wpse118772jsObject' );
function wpse118772jsObject()
{
$scriptHandle = 'custom-script-name';
// Dovrebbe essere diviso in funzioni o metodi separati
wp_register_script(
$scriptHandle,
plugins_url( __FILE__, 'your/path' ),
array( 'jquery' ),
plugin_dir_path( __FILE__ ).'your/path' ),
true
);
wp_enqueue_script( $scriptHandle );
wp_localize_script(
$scriptHandle,
'pluginObject',
array(
'ajaxURl' => admin_url( 'admin_ajax.php' ),
'custom' => array(
// dati personalizzati qui
),
),
);
}
Come usare jQuery AJAX nel modo corretto
Ci sono diverse funzioni che puoi usare: la funzione predefinita $.ajax({});
o le sue scorciatoie $.post();
, $.getJSON();
, ecc.
Quindi puoi semplicemente usare qualcosa come il seguente - utilizzando i metodi dell'oggetto success/fail
.
( function( $, plugin ) {
"use strict";
$.ajax( {
url : plugin.ajaxURl,
data : {
// altri dati
},
// Assumiamo che tu risponda con un wp_send_json_success/error() corretto nel callback PHP.
dataType : "json",
// Trasformazione della richiesta possibile qui.
beforeSend : function( xhr ) {
// Esempio:
// xhr.overrideMimeType( 'application/json' );
},
// I gestori effettivi
success : function( data, textStatus, jqXHR ) {
// Gestisci la trasformazione dei dati o la manipolazione del DOM qui.
},
error : function( jqXHR, textStatus, errorThrown ) {
// silenzioso: Registra l'errore
console.info( errorThrown );
// rumoroso: Lancia un'eccezione
throw errorThrown;
}
} );
} )( jQuery, pluginObject || {} );
Se vuoi andare più in profondità e fare le cose davvero nel modo giusto, dovrai usare il method chaining. (C'è ancora spazio per miglioramenti).
( function( $, plugin ) {
"use strict";
$.ajax( {
url : plugin.ajaxURl,
data : {
// altri dati
},
} )
.done( function( data ) {
// Gestisce solo risposte di successo
} )
.fail( function( reason ) {
// Gestisce solo errori
console.debug( reason );
} )
.always( function( data, textStatus, response ) {
// Se vuoi separare manualmente le cose
// response diventa errorThrown/reason OPPURE jqXHR in caso di successo
} )
.then( function( data, textStatus, response ) {
// Se lavori con una deferred.promise, usa questo metodo
// Di nuovo, dovrai separare manualmente successo/errore
} );
} )( jQuery, pluginObject || {} );
Nota: Per esempi migliori del wrapper attorno al callback, dai un'occhiata a commonjs o AMD e alle loro differenze.
Aspettare altre risposte AJAX
La parte interessante - e più potente - di tutta la gestione AJAX di jQuery (e altre librerie) è come aspettare che A sia terminato per poi avviare B e la sua elaborazione. La risposta è il caricamento "deferred" e le "promises".
Aggiungerò un esempio veloce. Dovresti forse pensare di costruire un oggetto e separare le cose aggiungendole via this.
all'oggetto, ma per un esempio il seguente dovrebbe essere sufficiente:
Esempio (A) Questo è fondamentalmente come lo faccio io. Dovrai riempire i pezzi da solo.
( function( $, plugin ) {
"use strict";
$.when(
$.ajax( {
url : pluginURl,
data : { /* ... */ }
} )
.done( function( data ) {
// 2a chiamata terminata
} )
.fail( function( reason ) {
console.info( reason );
} )
)
// Di nuovo, potresti usare .done(). Vedi la documentazione di jQuery.
.then(
// Successo
function( response ) {
// È andato a buon fine
// In caso di più richieste, entrambe devono avere successo
},
// Fallimento
function( resons ) {
// Ha generato un errore
// in caso di errori multipli, lancia il primo
},
);
} )( jQuery, pluginObject || {} );
Esempio (B) Non l'ho mai provato così, ma dovrebbe funzionare comunque. Più facile da leggere, ma preferisco le promesse risolte con $.when()
.
( function( $, plugin ) {
"use strict";
$.ajax( {
url : plugin.ajaxURl,
data : {
// altri dati
}
} )
.done( function( data ) {
// Gestisce solo risposte di successo
} )
.fail( function( reason ) {
console.info( reason );
} )
// Promise terminata:
.then( function( data ) {
$.ajax( {
url : pluginURl,
data : { /* ... */ }
} )
.done( function( data ) {
// 2a chiamata terminata
} )
.fail( function( reason ) {
console.info( reason );
} );
} );
} )( jQuery, pluginObject || {} );
Se vuoi approfondire ancora di più, leggi la documentazione su deferred
e then
.
async/ await
MODIFICA Poiché questa risposta riceve molta attenzione nel corso degli anni e ha già 8 anni, dai un'occhiata al seguente snippet.
Tieni presente che async/await
lavora ancora con le Promises. È solo zucchero sintattico. Tieni anche presente a cosa si riferisce this
quando usi funzioni abbreviate come visto in handlerB()
.
Questo funzionerà anche con jQuery.
( function( $, plugin ) {
const handlerA = async function( plugin ) {
try {
let res = await $.ajax( {
url : plugin.ajaxURl,
data : { /* alcuni dati */ }
} )
.done( function( data ) {
// Gestisce solo risposte di successo
} )
.fail( function( reason ) {
console.error( reason );
} )
return res;
} catch ( err ) {
console.error( err )
}
}
const handlerB = async data => { /* un'altra richiesta AJAX */ }
// Esegui
// …aspetta…
let $resultA = await handlerA( plugin )
// Ora esegui B
let $resultB = await handlerB( $resultA )
// Fai qualcosa con $resultB
} )( jQuery, pluginObject || {} );

In realtà non sto utilizzando alcun plugin. Una semplice chiamata AJAX di WordPress. Per quanto riguarda il problema del ritardo del server - Firebug mostra che la richiesta AJAX è completata senza dati ricevuti. Lasciami analizzare la tua risposta più in dettaglio.

@IstiaqueAhmed La descrizione sopra non è pensata per essere un plugin. Solo la base per scrivere il tuo plugin (o, nel caso in cui non ti interessi la separazione delle responsabilità, il tuo tema).

Grazie, questo è stato di grande aiuto in un progetto recente. Ho già votato positivamente molto tempo fa ;-) Volevo anche solo menzionare che le callback success
, error
, complete
sono ora deprecate a favore delle promise callback menzionate nella risposta.

@birgire Per favore [modifica] la risposta. Ho verificato e solo la prima parte è ora deprecata. Grazie in anticipo e grazie per le gentili parole :)

@kaiser negli esempi 'In attesa di altre risposte AJAX' A e B, dove si trovano esattamente le seconde chiamate ajax? Non riesco a vedere una seconda chiamata ajax nell'Esempio A.

Per eseguire una richiesta AJAX dopo il completamento di un'altra richiesta AJAX, devi aggiungere la seguente riga:
async: false,
Ovvero, devi aggiungere async: false
nel metodo ajax come mostrato di seguito:
$.ajax( { url : base_url+"/wp-admin/admin-ajax.php", type : 'GET', async: false,
