jquery - valore di ritorno utilizzando il risultato ajax in caso di successo


95

Ho un piccolo problema con la funzione jquery $ .ajax ().

Ho un modulo in cui ogni clic sul pulsante di opzione o selezione dal menu a discesa crea una variabile di sessione con il valore selezionato.

Ora - ho uno dei menu a discesa che hanno 4 opzioni - il primo (con etichetta Nessuno) ha un valore = "" altri hanno i loro ID.

Quello che voglio che accada è l'opzione Nessuna (con valore vuoto) per rimuovere la sessione e l'altra per crearne una, ma solo se la sessione con questo nome di selezione specifico non esiste già, poiché tutte le altre opzioni hanno lo stesso importo assegnato ad essa - indica solo quale è stato selezionato.

Non sono sicuro che abbia senso, ma dai un'occhiata al codice, forse questo lo renderà più chiaro:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            if(isSession(name) == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
});

quindi - prima di tutto quando il menu di selezione #add_ons attiva il "cambiamento" otteniamo alcuni valori da alcuni elementi per i calcoli.

otteniamo l'attributo label dell'opzione dalla nostra selezione che memorizza il valore da aggiungere al totale, il nome della selezione per creare la sessione con questo nome e il valore per verificare successivamente quale è stata selezionata.

ora - controlliamo se val == "" (che indicherebbe che è stata selezionata l'opzione Nessuno) e deduciamo l'importo dal totale e rimuoviamo la sessione con il nome della selezione.

Dopo questo è dove inizia il problema - istruzione else.

Altrimenti - vogliamo controllare se la funzione isSession () con il nome del nostro selettore restituisce 0 o 1 - se restituisce 0 allora aggiungiamo al totale il valore memorizzato nell'attributo label, ma se restituisce 1 - questo suggerirebbe quella sessione esiste già - quindi modifichiamo il valore di questa sessione solo ricreandola - ma l'importo non viene aggiunto.

Ora la funzione isSession ha questo aspetto:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Ora - il problema è - che non so se l'uso di "return" restituirà il risultato dalla funzione - poiché non sembra funzionare - tuttavia, se metto i "dati" nella sezione success: nella avviso: sembra restituire il valore corretto.

Qualcuno sa come restituire il valore dalla funzione e quindi confrontarlo nell'istruzione successiva?


Grazie ragazzi, l'ho provato nel modo seguente:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            updateResult(data);
        },
        error: function() {
            alert('Error occured');
        }
    });
}

quindi la funzione updateResult ():

funzione updateResult (dati) {risultato = dati; }

risultato - è la variabile globale - che sto quindi cercando di leggere:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            isSession(name);
            if(result == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
    });

ma per qualche motivo - non funziona - qualche idea?



Essa può aiutare a risolvere questo problema: stackoverflow.com/questions/14220321/...
mirzaei.sajad

Risposte:


114

Il problema è che non puoi restituire un valore da una chiamata asincrona, come una richiesta AJAX, e aspettarti che funzioni.

Il motivo è che il codice in attesa della risposta è già stato eseguito nel momento in cui viene ricevuta la risposta.

La soluzione a questo problema è eseguire il codice necessario all'interno del success:callback. In questo modo accede dataall'unico quando è disponibile.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            // Run the code here that needs
            //    to access the data returned
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Un'altra possibilità (che è effettivamente la stessa cosa) è chiamare una funzione all'interno del success:callback che passa i dati quando sono disponibili.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
                // Call this function on success
            someFunction( data );
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

function someFunction( data ) {
    // Do something with your data
}

11
È POSSIBILE restituire un valore da una richiesta AJAX, ma solo se lo rendi non asincrono (imposta l'opzione async: false). In alcuni casi, non è necessario disporre di una chiamata asincrona. Altro su jquery.ajax () doc api.jquery.com/jQuery.ajax , non quelloAs of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated;
Adrien Be

48
"Non asincrono" può ovviamente essere definito anche "sincrono";)
Charles Wood

in entrambi i metodi che hai suggerito; cioè. eseguire la funzione con successo, quindi è necessario scrivere più ajax per diversi scenari. questo non aiuterà nella creazione di un wrapper ajax globale, motore.
wpcoder

Sembra, async: false è ora deprecato e tutta l'elaborazione deve essere eseguita nelle funzioni di callback.
Puneet Lamba,

31

Esistono molti modi per ottenere la risposta jQuery AJAX. Condivido con voi due approcci comuni:

Primo:

usa async = false e all'interno della funzione restituisci ajax-object e successivamente ottieni la risposta ajax-object.responseText

/**
 * jQuery ajax method with async = false, to return response
 * @param  {mix}  selector - your selector
 * @return {mix}           - your ajax response/error
 */
function isSession(selector) {
    return $.ajax({
        type: "POST",
        url: '/order.html',
        data: {
            issession: 1,
            selector: selector
        },
        dataType: "html",
        async: !1,
        error: function() {
            alert("Error occured")
        }
    });
}
// global param
var selector = !0;
// get return ajax object
var ajaxObj = isSession(selector);
// store ajax response in var
var ajaxResponse = ajaxObj.responseText;
// check ajax response
console.log(ajaxResponse);
// your ajax callback function for success
ajaxObj.success(function(response) {
    alert(response);
});

Secondo:

usa il metodo $ .extend e crea una nuova funzione come ajax

/**
 * xResponse function
 *
 * xResponse method is made to return jQuery ajax response
 * 
 * @param  {string} url   [your url or file]
 * @param  {object} your ajax param
 * @return {mix}       [ajax response]
 */
$.extend({
    xResponse: function(url, data) {
        // local var
        var theResponse = null;
        // jQuery ajax
        $.ajax({
            url: url,
            type: 'POST',
            data: data,
            dataType: "html",
            async: false,
            success: function(respText) {
                theResponse = respText;
            }
        });
        // Return the response text
        return theResponse;
    }
});

// set ajax response in var
var xData = $.xResponse('temp.html', {issession: 1,selector: true});

// see response in console
console.log(xData);

puoi renderlo grande quanto vuoi ...


Bella idea ma ajaxObj['responseText']non esiste quando stai definendovar ajaxResponse
mu3

Perfetto!! la tua prima soluzione mi ha salvato
Kallel Omar

il secondo metodo è 100% OK! ;)
Schalk Keun

7
A partire da jQuery 1.8, l'uso di async: false è deprecato!
gatteo

10

Ho visto le risposte qui e, sebbene utili, non erano esattamente ciò che volevo poiché ho dovuto modificare molto del mio codice.

Quello che ha funzionato per me, è stato fare qualcosa del genere:

function isSession(selector) {
    //line added for the var that will have the result
    var result = false;
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        //line added to get ajax response in sync
        async: false,
        success: function(data) {
            //line added to save ajax response in var result
            result = data;
        },
        error: function() {
            alert('Error occured');
        }
    });
    //line added to return ajax response
    return result;
}

La speranza aiuta qualcuno

anakin


4
In realtà disattivi l'asincronia
Weijing Jay Lin

4

Sebbene tutti gli approcci riguardanti l'uso di async: falsenon siano buoni a causa della sua deprecazione e bloccano la pagina fino a quando la richiesta non torna. Quindi qui ci sono 2 modi per farlo:

1 °: restituisce l'intera risposta ajax in una funzione e quindi utilizza la donefunzione per acquisire la risposta quando la richiesta è stata completata. (CONSIGLIATO, IL MODO MIGLIORE)

function getAjax(url, data){
    return $.ajax({
        type: 'POST',
        url : url,              
        data: data,
        dataType: 'JSON',
        //async: true,  //NOT NEEDED
        success: function(response) {
            //Data = response;
        }
    });
 }

CHIAMARE QUANTO SOPRA COME COSÌ:

getAjax(youUrl, yourData).done(function(response){
    console.log(response);
});

PER CHIAMATE MULTIPLE AJAX UTILIZZARE $.when:

$.when( getAjax(youUrl, yourData), getAjax2(yourUrl2, yourData2) ).done(function(response){
    console.log(response);
});

2 °: memorizza la risposta in un cookie e quindi al di fuori della chiamata ajax ottieni quel valore del cookie. (NON RACCOMANDATO)

        $.ajax({
            type: 'POST',
            url : url,              
            data: data,
            //async: false,    // No need to use this
            success: function(response) {
                Cookies.set(name, response);
            }
        });

        // Outside of the ajax call
        var response = Cookies.get(name);

NOTA: Nell'esempio sopra jquery cookiesviene utilizzata la libreria, che è abbastanza leggera e funziona in modo scattante. Ecco il link https://github.com/js-cookie/js-cookie


3

Aggiungi async: falseal tuo elenco di attributi. Ciò forza il thread javascript ad attendere fino a quando il valore restituito viene recuperato prima di procedere. Ovviamente, non vorresti farlo in ogni circostanza, ma se è necessario un valore prima di procedere, questo lo farà.


3
Non dovresti mai e poi mai impostare async: false. Questo blocca tutto sulla pagina per la durata del recupero. Sai cosa significa la A in AJAX: Asynchronous. La risposta corretta sarebbe che OP deve utilizzare success()correttamente la richiamata.
nietonfir

2
Ho riconosciuto il fatto che tutto deve aspettare. In determinate circostanze, la funzione chiamante potrebbe richiedere un valore restituito, ad esempio l'aggiunta di un nuovo record e la restituzione di un ID record. Una volta che conosci le regole, sai quando possono essere violate. Mai dire mai. Ecco qualcun altro che è d'accordo. ( stackoverflow.com/questions/3880361/… )
Hoodlum

1
@CharlesWood Solo per coloro che non riescono a cogliere la natura asincrona di ajax.
nietonfir

1
@nietonfir: se non dovessi mai usare, async: falseperché jQuery avrebbe implementato questa opzione? se non carico grandi quantità di dati nella pagina e gestisco solo un evento utente, va bene che blocchi tutto il resto nel breve lasso di tempo per quel particolare utente. niente di sbagliato e niente di male. (se usato correttamente non bloccherà nulla perché in quel particolare momento non si verificheranno altre azioni per quel particolare utente)
low_rents

1
@northkildonan No, non va bene. Una richiesta di sincronizzazione AJAX non è valida. Blocca il thread javascript completo con qualcosa che non puoi controllare. Non hai il controllo sul tempo necessario per elaborare la richiesta: la connessione potrebbe essere inaffidabile, il server potrebbe impiegare più tempo del previsto, ecc. L' unico motivo per cui è in jQuery è che potresti aver bisogno di salvare i dati sullo scaricamento della pagina (l'unico posto non importa se impiega più tempo, poiché l'utente ha già espresso il desiderio di lasciare la pagina). Basta guardare gli unit test di jQuery ...
nietonfir

3

Questo è abbastanza vecchio e brutto, non farlo. Dovresti usare i callback: https://stackoverflow.com/a/5316755/591257
Ha avuto lo stesso problema, l'ho risolto in questo modo, usando una var globale. Non sono sicuro che sia il migliore ma sicuramente funziona. In caso di errore si ottiene una stringa vuota (myVar = ''), quindi è possibile gestirla secondo necessità.

var myVar = '';
function isSession(selector) {
  $.ajax({
    'type': 'POST',
    'url': '/order.html',
    'data': {
      'issession': 1,
      'selector': selector
    },
    'dataType': 'html',
    'success': function(data) {
      myVar = data;
    },
    'error': function() {
      alert('Error occured');
    }
  });
  return myVar;
}

3
devi anche aggiungere async: falsequi, perché in modalità asincrona non è garantito che datavenga salvato myVarprima che myVarvenga restituito.
low_rents

2
// Common ajax caller
function AjaxCall(url,successfunction){
  var targetUrl=url;
  $.ajax({
    'url': targetUrl,
    'type': 'GET',
    'dataType': 'json',
    'success': successfunction,
    'error': function() {
      alert("error");
    }
  });
}

// Calling Ajax
$(document).ready(function() {
  AjaxCall("productData.txt",ajaxSuccessFunction);
});

// Function details of success function
function ajaxSuccessFunction(d){
  alert(d.Pioneer.Product[0].category);
}

può aiutare, creare una funzione di chiamata ajax comune e allegare una funzione che invoca quando ha successo la chiamata ajax, vedere l'esempio


1

Con aiuto da qui

function get_result(some_value) {
   var ret_val = {};
   $.ajax({
       url: '/some/url/to/fetch/from',
       type: 'GET',
       data: {'some_key': some_value},
       async: false,
       dataType: 'json'
   }).done(function (response) {
       ret_val = response;
   }).fail(function (jqXHR, textStatus, errorThrown) {
           ret_val = null;
       });
   return ret_val;
}

Spero che questo aiuti qualcuno da qualche parte.


L'uso di async: false,è preistorico ed è deprecato da jQuery v1.8, probabilmente non aiuterà nessuno
Alon Eitan

-2

Ciao, prova async: false nella tua chiamata ajax ..

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.