Execută o cerere AJAX după ce o altă cerere AJAX s-a finalizat

14 oct. 2013, 12:08:59
Vizualizări: 177K
Voturi: 6

Un fișier JS face un apel ajax. În cadrul succesului acestui apel ajax se face un alt apel AJAX. Al doilea apel verifică dacă emailul a fost deja înregistrat. Dacă a fost înregistrat, atunci al doilea apel AJAX nu primește date returnate, așa cum se arată în Firebug și consola Chrome în acest caz. Dar același cod funcționează perfect în localhost în timp ce problema menționată apare DOAR pe serverul online.

Pagina găzduită este la http://twmobilefitness.com/signup/. Problema apare când faci clic pe link-ul 'Register Now' de la final. Trebuie să te înregistrezi de două ori cu aceeași adresă de email dacă vrei să reproduci 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">Numele de utilizator nu este disponibil </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">Emailul este deja folosit </span>' );
                    } else if ( parseInt( result_email ) == 1 ) {
                        $( ".result" ).html( '' );      
                        $( ".signup_div" ).hide();
                        $( ".signup_emergency_contact" ).show();
                    }
                }
            } );
        }
    }   
} );    

functions.php are

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();
}

Cum pot face codul să funcționeze pe serverul online?

0
Toate răspunsurile la întrebare 2
7
14

Ceea ce experimentați (AJAX funcționează local, dar nu pe server) este o problemă de întârziere. Local totul funcționează atât de repede, încât nu puteți vedea problema. Pe scurt, aceasta este problema dumneavoastră:

Callback-ul AJAX (A) se execută > Callback-ul AJAX (B) nu știe că trebuie să aștepte după (A) > Nu puteți vedea problema în instalarea locală, deoarece (A) se termină prea repede.

Așadar, trebuie să găsiți o modalitate de a-i spune Callback-ului (B) că trebuie să aștepte după (A). Iată cum:

Înregistrați scripturile și mutați datele din PHP în JS

Înregistrați și încărcați corect datele localizate: Înfășurați-le într-o funcție sau metodă și conectați-o la wp_enqueue_scripts (public/teme), login_enqueue_scripts (parolă/autentificare/înregistrare) sau admin_enqueue_scripts. Apoi utilizați wp_localize_script() pentru a muta datele din PHP în JS și a le face accesibile acolo.

add_action( 'admin_enqueue_scripts', 'wpse118772jsObject' );
function wpse118772jsObject()
{
    $scriptHandle = 'custom-script-name';
    // Ar trebui să fie împărțit în funcții sau metode separate
    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(
                        // date personalizate aici
                ),
        ),
    );
}

Cum să utilizați corect jQuery AJAX.

Există mai multe funcții pe care le puteți utiliza: funcția implicită $.ajax({}); sau scurtăturile acesteia $.post();, $.getJSON();, etc.

Așadar, puteți utiliza pur și simplu ceva de genul următor - folosind metodele obiectului success/fail.

( function( $, plugin ) {
    "use strict";

    $.ajax( {
        url : plugin.ajaxURl,
        data : {
            // alte date
        },
        // Presupunem că răspundeți cu un wp_send_json_success/error() corespunzător în Callback-ul PHP.
        dataType : "json",

        // Transformarea cererii este posibilă aici.
        beforeSend : function( xhr ) {
            // Exemplu:
            // xhr.overrideMimeType( 'application/json' );
        },

        // Gestionare efectivă
        success : function( data, textStatus, jqXHR ) {
            // Manipulați transformarea datelor sau manipularea DOM aici.
        },
        error : function( jqXHR, textStatus, errorThrown ) {
            // silent: Înregistrați eroarea
            console.info( errorThrown );
            // loud: Aruncați excepție
            throw errorThrown;
        }
    } );
} )( jQuery, pluginObject || {} );

Dacă doriți să intrați mai în profunzime și să faceți lucrurile într-adevăr corect, va trebui să utilizați înlănțuirea metodelor. (Mai este loc pentru îmbunătățiri).

( function( $, plugin ) {
    "use strict";

    $.ajax( {
        url : plugin.ajaxURl,
        data : {
            // alte date
        },
    } )
        .done( function( data ) {
            // Gestionați doar răspunsurile de succes
        } )
        .fail( function( reason ) {
            // Gestionați doar erorile
            console.debug( reason );
        } )
        .always( function( data, textStatus, response ) {
            // Dacă doriți să separați manual lucrurile
            // response devine errorThrown/reason SAU jqXHR în caz de succes
        } )
        .then( function( data, textStatus, response ) {
            // În cazul în care lucrați cu un deferred.promise, utilizați această metodă
            // Din nou, va trebui să separați manual succesul/eroarea
        } );
} )( jQuery, pluginObject || {} );

Notă: Pentru exemple mai bune ale învelișului în jurul callback-ului, consultați commonjs sau AMD și diferențele dintre ele.

Așteptarea altor răspunsuri AJAX

Partea interesantă - și cea mai puternică a întregii gestionări AJAX în jQuery (și alte biblioteci) - este cum să așteptați până când A se termină pentru a începe apoi B și procesarea acestuia. Răspunsul este încărcarea "amânată" și "promisiunile".

Voi adăuga un exemplu rapid. Ar trebui să vă gândiți poate la construirea unui obiect și separarea lucrurilor prin adăugarea lor via this. la obiect, dar pentru un exemplu, următoarele ar trebui să fie suficiente:

Exemplu (A) Acesta este în principiu cum o fac eu. Va trebui să completați detaliile singur.

( function( $, plugin ) {
    "use strict";

    $.when(
        $.ajax( {
            url :  pluginURl,
            data : { /* ... */ }
        } )
           .done( function( data ) {
                // Al doilea apel s-a terminat
           } )
           .fail( function( reason ) {
               console.info( reason );
           } )
        )
        // Din nou, ați putea utiliza .done(). Consultați documentația jQuery.
        .then( 
            // Succes
            function( response ) {
                // A avut succes
                // În cazul mai multor cereri, ambele trebuie să aibă succes
            },
            // Eșec
            function( resons ) {
                // A generat o eroare
                // în cazul mai multor erori, aruncă prima
            },
        );
} )( jQuery, pluginObject || {} );

Exemplu (B) Nu am încercat niciodată așa, dar ar trebui să funcționeze și așa. Mai ușor de citit, dar mie îmi place mai mult rezolvarea cu $.when().

( function( $, plugin ) {
    "use strict";

    $.ajax( {
        url : plugin.ajaxURl,
        data : {
            // alte date
        }
    } )
        .done( function( data ) {
            // Gestionați doar răspunsurile de succes
        } )
        .fail( function( reason ) {
            console.info( reason );
        } )
        // Promisiune finalizată:
        .then( function( data ) {
            $.ajax( {
                url :  pluginURl,
                data : { /* ... */ }
            } )
                .done( function( data ) {
                    // Al doilea apel s-a terminat
                } )
                .fail( function( reason ) {
                    console.info( reason );
                } );
        } );
} )( jQuery, pluginObject || {} );

Dacă doriți să intrați și mai în profunzime, citiți documentația despre deferred și then.

async/ await

EDITARE Deoarece acest răspuns primește destul de multă atenție de-a lungul anilor și are deja 8 ani, vă rugăm să consultați următorul fragment.

Rețineți că async/await încă se ocupă de Promisiuni. Este doar zahăr sintetic. De asemenea, rețineți la ce se referă this când utilizați funcții prescurtate, cum se vede în handlerB().

Asta va funcționa chiar și cu jQuery.

( function( $, plugin ) {
    const handlerA = async function( plugin ) {
        try {
            let res = await $.ajax( {
                url : plugin.ajaxURl,
                data : { /* unele date */ }
            } )
                .done( function( data ) {
                    // Gestionați doar răspunsurile de succes
                } )
                .fail( function( reason ) {
                    console.error( reason );
                } )
            return res;
        } catch ( err ) {
            console.error( err )
        }
    }
    const handlerB = async data => { /* încă o cerere AJAX */ }

    // Executați
    // …așteptați…
    let $resultA = await handlerA( plugin )
    // Acum executați B
    let $resultB = await handlerB( $resultA )

    // Faceți ceva cu $resultB

} )( jQuery, pluginObject || {} );
14 oct. 2013 16:28:02
Comentarii

de fapt, nu folosesc niciun plugin. Doar un simplu apel AJAX în WordPress. În legătură cu problema de întârziere a serverului - Firebug arată că cererea AJAX s-a încheiat, dar nu a primit niciun date. Lasă-mă să analizez mai profund răspunsul tău.

Istiaque Ahmed Istiaque Ahmed
14 oct. 2013 17:32:08

@IstiaqueAhmed Descrierea de mai sus nu este menită să fie vreun plugin. Doar o bază pentru a-ți scrie propriul plugin (sau, în cazul în care nu-ți pasă de separarea preocupărilor, propria ta temă).

kaiser kaiser
14 oct. 2013 17:38:47

Mulțumesc, acest lucru a fost de mare ajutor într-un proiect recent. Deja am votat demult ;-) De asemenea, voiam doar să menționez că funcțiile de callback success, error, complete sunt acum depreciate în favoarea celor de tip promise menționate în răspuns.

birgire birgire
14 aug. 2015 17:52:20

@birgire Te rog să [editezi] răspunsul. Am verificat și doar prima parte este acum învechită. Mulțumesc anticipat și mulțumesc pentru cuvintele frumoase :)

kaiser kaiser
15 aug. 2015 14:05:16

Acest răspuns este atât de frumos scris. +1

Ahmed Alhallag Ahmed Alhallag
21 iul. 2021 20:19:04

@kaiser în exemplele 'Așteptând alte răspunsuri AJAX' A și B, unde sunt exact cele de-al doilea apeluri ajax? Nu văd un al doilea apel ajax în Exemplul A.

HappyCoding HappyCoding
31 dec. 2021 18:17:49

@HappyCoding vezi constant handlerB

kaiser kaiser
6 ian. 2022 16:02:16
Arată celelalte 2 comentarii
0

Pentru a executa o cerere AJAX după finalizarea altei cereri AJAX, trebuie să adăugați următoarea linie,

 
    async: false,

adică, trebuie să adăugați async: false în metoda ajax, după cum urmează,

$.ajax( {
    url : base_url+"/wp-admin/admin-ajax.php",
    type : 'GET',
    async: false,
9 ian. 2019 07:11:42