jquery - Rückgabewert mit Ajax-Ergebnis bei Erfolg

94

Ich habe ein kleines Problem mit der Funktion jquery $ .ajax ().

Ich habe ein Formular, in dem jeder Klick auf das Optionsfeld oder jede Auswahl aus dem Dropdown-Menü eine Sitzungsvariable mit dem ausgewählten Wert erstellt.

Jetzt - ich habe eines der Dropdown-Menüs mit 4 Optionen - hat das erste (mit der Bezeichnung None) den Wert = "" andere haben ihre IDs.

Was ich tun möchte, ist die Option Keine (mit leerem Wert), um die Sitzung zu entfernen, und die andere, um eine zu erstellen, aber nur, wenn die Sitzung mit diesem bestimmten ausgewählten Namen noch nicht vorhanden ist - da allen anderen Optionen der gleiche Betrag zugewiesen ist - Es zeigt nur an, welches ausgewählt wurde.

Ich bin mir nicht sicher, ob das Sinn macht - aber schauen Sie sich den Code an - vielleicht wird dies klarer:

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

Also - zuerst, wenn das Auswahlmenü #add_ons "change" auslöst, erhalten wir einige Werte von einigen Elementen für Berechnungen.

Wir erhalten das Label-Attribut der Option aus unserer Auswahl, in der der Wert gespeichert wird, der zur Gesamtsumme hinzugefügt werden soll, den Namen der Auswahl, um eine Sitzung mit diesem Namen zu erstellen, und den Wert, um später zu überprüfen, welcher ausgewählt wurde.

Jetzt prüfen wir, ob der Wert == "" (was darauf hinweist, dass die Option Keine ausgewählt wurde) und ziehen den Betrag von der Gesamtsumme ab und entfernen die Sitzung mit dem Namen der Auswahl.

Danach beginnt das Problem - else-Anweisung.

Andernfalls möchten wir überprüfen, ob die Funktion isSession () mit dem Namen unseres Selektors 0 oder 1 zurückgibt. Wenn sie 0 zurückgibt, addieren wir den im label-Attribut gespeicherten Wert zur Gesamtsumme. Wenn sie jedoch 1 zurückgibt, würde dies nahe legen Diese Sitzung ist bereits vorhanden. Dann ändern wir den Wert dieser Sitzung nur, indem wir sie neu erstellen. Der Betrag wird jedoch nicht hinzugefügt.

Jetzt sieht die isSession-Funktion folgendermaßen aus:

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

Nun - das Problem ist - dass ich nicht weiß, ob die Verwendung von "return" das Ergebnis der Funktion zurückgibt - da es nicht zu funktionieren scheint -, wenn ich die "Daten" in den Abschnitt "success:" in den Abschnitt " alert - es scheint den richtigen Wert zurückzugeben.

Weiß jemand, wie man den Wert von der Funktion zurückgibt und ihn dann in der nächsten Anweisung vergleicht?


Danke Jungs - ich habe es folgendermaßen versucht:

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

dann die Funktion updateResult ():

Funktion updateResult (Daten) {Ergebnis = Daten; }}

Ergebnis - ist die globale Variable - die ich dann zu lesen versuche:

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

aber aus irgendeinem Grund - es funktioniert nicht - irgendeine Idee?

user398341
quelle
Es kann helfen, dieses Problem zu lösen: stackoverflow.com/questions/14220321/…
mirzaei.sajad

Antworten:

113

Das Problem ist, dass Sie einen Wert aus einem asynchronen Aufruf wie einer AJAX-Anforderung nicht zurückgeben und erwarten können, dass er funktioniert.

Der Grund dafür ist, dass der auf die Antwort wartende Code zum Zeitpunkt des Empfangs der Antwort bereits ausgeführt wurde.

Die Lösung für dieses Problem ist den notwendigen Code auszuführen innerhalb des success:Rückrufs. Auf diese Weise greift es datanur dann zu, wenn es verfügbar ist.

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

Eine andere Möglichkeit (die praktisch dasselbe ist) besteht darin, eine Funktion in Ihrem success:Rückruf aufzurufen , die die Daten weiterleitet, sobald sie verfügbar sind.

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
}
user113716
quelle
11
Sie können einen Wert aus einer AJAX-Anforderung zurückgeben, dies ist jedoch nur möglich, wenn Sie ihn nicht asynchron machen (Option festlegen async: false). In einigen Fällen ist ein asynchroner Aufruf nicht erforderlich. Mehr auf jquery.ajax () doc api.jquery.com/jQuery.ajax , nicht dasAs of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated;
Adrien Be
48
"Nicht asynchron" kann natürlich auch als "synchron" bezeichnet werden;)
Charles Wood
in beiden Methoden haben Sie vorgeschlagen; dh. Führen Sie die Funktion mit Erfolg aus, dann müssen Sie mehrere Ajax für verschiedene Szenarien schreiben. Dies hilft nicht beim Erstellen einer globalen Ajax-Wrapper-Engine.
wpcoder
Es scheint, async: false ist jetzt veraltet und die gesamte Verarbeitung muss in den Rückruffunktionen durchgeführt werden.
Puneet Lamba
31

Es gibt viele Möglichkeiten, eine jQuery AJAX-Antwort zu erhalten. Ich teile mit Ihnen zwei gemeinsame Ansätze:

Zuerst:

Verwenden Sie async = false und geben Sie innerhalb der Funktion ajax-object zurück und erhalten Sie später die Antwort 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);
});

Zweite:

Verwenden Sie die Methode $ .extend und erstellen Sie eine neue Funktion wie 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);

Sie können es so groß machen, wie Sie wollen ...

Neeraj Singh
quelle
ajaxObj['responseText']var ajaxResponse
Gute
Perfekt!! Ihre erste Lösung hat mich gerettet
Kallel Omar
zweite Methode ist 100% A OK! ;)
Schalk Keun
7
Ab jQuery 1.8 ist die Verwendung von async: false veraltet!
Gatteo
10

Ich habe die Antworten hier gesehen und obwohl sie hilfreich waren, waren sie nicht genau das, was ich wollte, da ich einen Großteil meines Codes ändern musste.

Was für mich geklappt hat, war so etwas zu tun:

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

Hoffnung hilft jemandem

Anakin

Anakin
quelle
4
Sie schalten eigentlich nur
asynchron
4

Obwohl alle Ansätze in Bezug auf die Verwendung von async: falsenicht gut sind, weil es veraltet ist und die Seite stecken bleibt, bis die Anfrage zurückkommt. Es gibt also zwei Möglichkeiten, dies zu tun:

1. Geben Sie die gesamte Ajax-Antwort in einer Funktion zurück und verwenden Sie dann die doneFunktion, um die Antwort zu erfassen, wenn die Anforderung abgeschlossen ist. (EMPFOHLEN, DER BESTE WEG)

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

RUFEN SIE DAS OBIGE WIE SO AN:

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

FÜR MEHRERE AJAX-ANRUFE VERWENDEN SIE $.when:

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

2. Speichern Sie die Antwort in einem Cookie und erhalten Sie dann außerhalb des Ajax-Aufrufs diesen Cookie-Wert. (NICHT EMPFOHLEN)

        $.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);

HINWEIS: Im obigen Beispiel wird die jquery cookiesBibliothek verwendet. Sie ist recht leicht und funktioniert bissig. Hier ist der Link https://github.com/js-cookie/js-cookie

MR_AMDEV
quelle
3

Fügen Sie async: falseIhrer Attributliste hinzu. Dies zwingt den Javascript-Thread, zu warten, bis der Rückgabewert abgerufen wurde, bevor er fortfährt. Natürlich möchten Sie dies nicht unter allen Umständen tun, aber wenn ein Wert benötigt wird, bevor Sie fortfahren, wird dies getan.

Ganove
quelle
3
Sie sollten niemals einstellen async: false. Dies blockiert alles auf der Seite für die Dauer des Abrufs. Sie wissen, wofür das A in AJAX steht: Asynchron. Die richtige Antwort wäre, dass OP den success()Rückruf richtig verwenden muss.
Nietonfir
2
Ich habe die Tatsache anerkannt, dass alles warten muss. Unter bestimmten Umständen benötigt die aufrufende Funktion möglicherweise einen zurückgegebenen Wert, z. B. das Hinzufügen eines neuen Datensatzes und das Zurückgeben einer zurückgegebenen Datensatz-ID. Sobald Sie die Regeln kennen, wissen Sie, wann sie gebrochen werden können. Sag niemals nie. Hier ist jemand anderes, der zustimmt. ( stackoverflow.com/questions/3880361/… )
Hoodlum
1
@ CharlesWood Nur für diejenigen, die die asynchrone Natur von Ajax nicht verstehen können.
Nietonfir
1
@nietonfir: Wenn Sie niemals verwenden sollten, async: falsewarum hätte jQuery diese Option implementiert? Wenn ich keine großen Datenmengen auf die Seite lade und nur ein Benutzerereignis behandle, ist es in Ordnung, dass alles andere in der kurzen Zeit für diesen bestimmten Benutzer blockiert wird. nichts falsches und nichts schlechtes daran. (Bei korrekter Verwendung wird nichts blockiert, da in dieser bestimmten Zeit keine weiteren Aktionen für diesen bestimmten Benutzer ausgeführt werden.)
low_rents
1
@northkildonan Nein, es ist nicht in Ordnung. Eine AJAX-Synchronisierungsanforderung ist fehlerhaft. Es blockiert den gesamten Javascript-Thread mit etwas, das Sie nicht kontrollieren können. Sie haben keine Kontrolle darüber, wie lange es dauern kann, die Anforderung zu verarbeiten: Die Verbindung ist möglicherweise unzuverlässig, der Server dauert möglicherweise länger als erwartet usw. Der einzige Grund für jQuery besteht darin, dass Sie möglicherweise Daten speichern müssen beim Entladen der Seite (der einzige Ort, an dem es nicht wirklich wichtig ist, ob es länger dauert, da der Benutzer bereits seinen Wunsch zum Ausdruck gebracht hat, die Seite zu verlassen). Schauen Sie sich einfach die jQuery-Unit-Tests an…
Nietonfir
3

Das ist ziemlich alt und hässlich, tu das nicht. Sie sollten Rückrufe verwenden: https://stackoverflow.com/a/5316755/591257
Hatte das gleiche Problem und löste es auf diese Weise mit einer globalen Variable. Ich bin mir nicht sicher, ob es das Beste ist, aber es funktioniert auf jeden Fall. Bei einem Fehler erhalten Sie eine leere Zeichenfolge (myVar = ''), sodass Sie diese nach Bedarf behandeln können.

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;
}
aesede
quelle
3
Sie müssen async: falsehier auch hinzufügen , da im asynchronen Modus nicht garantiert ist, dass datagespeichert wird, myVarbevor myVares zurückgegeben wird.
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);
}

Es kann hilfreich sein, eine allgemeine Ajax-Aufruffunktion zu erstellen und eine Funktion anzuhängen, die bei Erfolg den Ajax-Aufruf aufruft (siehe Beispiel)

Binson
quelle
1

Mit Hilfe von hier

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

Hoffe das hilft jemandem irgendwo ein bisschen.

Muhammad Nahid
quelle
Die Verwendung von async: false,ist prähistorisch und seit jQuery v1.8 veraltet. Es wird wahrscheinlich niemandem helfen
Alon Eitan
-2

Hallo, versuche asynchron: false in deinem Ajax-Aufruf.

Kathir
quelle