it-swarm.com.de

jQuery: Daten nach erfolgreichem Ajax-Aufruf zurückgeben

Ich habe so etwas, bei dem es sich um einen einfachen Aufruf eines Skripts handelt, das mir einen Wert zurückgibt, eine Zeichenfolge.

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {
         return data; 
      }
   });
}

aber wenn ich so etwas nenne

var output = testAjax(svar);  // output will be undefined...

wie kann ich den Wert zurückgeben? Der folgende Code scheint auch nicht zu funktionieren ...

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {

      }
   });
   return data; 
}
435
Francesco

Die einzige Möglichkeit, die Daten von der Funktion zurückzugeben, besteht darin, einen synchronen statt eines asynchronen Aufrufs zu tätigen. Dadurch wird der Browser jedoch eingefroren, während er auf die Antwort wartet.

Sie können eine Rückruffunktion übergeben, die das Ergebnis verarbeitet:

function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",  
    success:function(data) {
      handleData(data); 
    }
  });
}

Nenne es so:

testAjax(function(output){
  // here you use the output
});
// Note: the call won't wait for the result,
// so it will continue with the code here while waiting.
364
Guffa

Hinweis: Diese Antwort wurde im Februar 2010 verfasst.
Siehe Updates von 2015, 2016 und 2017 unten.

Sie können von einer asynchronen Funktion nichts zurückgeben. Was Sie zurückgeben können, ist ein Versprechen . In meinen Antworten auf diese Fragen habe ich erklärt, wie Versprechen in jQuery funktionieren:

Wenn Sie erklären könnten , warum Sie die Daten zurückgeben möchten und was Sie später damit machen möchten, dann könnte ich Ihnen vielleicht eine geben Genauere Antwort, wie es geht.

Im Allgemeinen anstelle von:

function testAjax() {
  $.ajax({
    url: "getvalue.php",  
    success: function(data) {
      return data; 
    }
  });
}

sie können Ihre testAjax-Funktion folgendermaßen schreiben:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

Dann können Sie Ihr Versprechen so erhalten:

var promise = testAjax();

Sie können Ihr Versprechen speichern, Sie können es weitergeben, Sie können es als Argument in Funktionsaufrufen verwenden und Sie können es von Funktionen zurückgeben, aber wenn Sie schließlich verwenden möchten Ihre Daten, die vom AJAX -Aufruf zurückgegeben werden, müssen Sie folgendermaßen ausführen:

promise.success(function (data) {
  alert(data);
});

(Vereinfachte Syntax siehe Updates unten.)

Wenn Ihre Daten zu diesem Zeitpunkt verfügbar sind, wird diese Funktion sofort aufgerufen. Ist dies nicht der Fall, wird es aufgerufen, sobald die Daten verfügbar sind.

Der springende Punkt dabei ist, dass Ihre Daten nicht unmittelbar nach dem Aufruf von $ .ajax verfügbar sind, da sie asynchron sind. Promises ist eine nette Abstraktion für Funktionen, die sagen: Ich kann Ihnen die Daten nicht zurückgeben, da ich sie noch nicht habe und Sie nicht blockieren und warten lassen möchte. Hier ist also ein Versprechen stattdessen und Sie können es später verwenden oder es einfach an eine andere Person weitergeben und damit fertig sein.

Siehe hierzu DEMO .

UPDATE (2015)

Derzeit (Stand März 2015) sind jQuery Promises nicht mit der Promises/A + -Spezifikation kompatibel, was bedeutet, dass sie möglicherweise nicht sehr gut mit anderen Promises/A + -konformen Implementierungen zusammenarbeiten.

Allerdings wird jQuery Promises in der kommenden Version 3.x mit der Promises/A + -Spezifikation kompatibel sein (danke an Benjamin Gruenbaum für darauf hinweisen). Derzeit (Stand Mai 2015) sind die stabilen Versionen von jQuery 1.x und 2.x.

Was ich oben (im März 2011) erklärt habe, ist eine Möglichkeit, jQuery Deferred Objects zu verwenden, um etwas asynchrones zu tun, das im synchronen Code durch die Rückgabe eines Werts erreicht würde.

Ein synchroner Funktionsaufruf kann jedoch zwei Aufgaben ausführen: Er kann entweder einen Wert zurückgeben (falls möglich) oder eine Ausnahme auslösen (falls kein Wert zurückgegeben werden kann). Promises/A + behandelt beide Anwendungsfälle auf eine Weise, die so leistungsfähig ist wie die Ausnahmebehandlung in synchronem Code. Die jQuery-Version verarbeitet das Äquivalent der Rückgabe eines Werts, aber das Äquivalent der komplexen Ausnahmebehandlung ist etwas problematisch.

Insbesondere ist der springende Punkt der Ausnahmebehandlung in synchronem Code nicht nur das Aufgeben einer Nice-Nachricht, sondern der Versuch, das Problem zu beheben und die Ausführung fortzusetzen, oder möglicherweise die gleiche oder eine andere Ausnahme für einige andere Teile des Programms erneut auszulösen Griff. Im synchronen Code haben Sie einen Aufrufstapel. Bei asynchronen Aufrufen können Sie nicht und die erweiterte Ausnahmebehandlung innerhalb Ihrer Versprechen, wie in der Promises/A + -Spezifikation gefordert, Ihnen dabei helfen, Code zu schreiben, der Fehler und Ausnahmen auch in komplexen Anwendungsfällen auf sinnvolle Weise behandelt.

Unterschiede zwischen jQuery und anderen Implementierungen sowie Informationen zum Konvertieren von jQuery-Versprechen in Versprechen/A + -kompatibel finden Sie unter Aus jQuery von Kris Kowal et al. im Wiki der Q-Bibliothek und Versprechen treffen in JavaScript ein von Jake Archibald auf HTML5 Rocks.

Wie man ein echtes Versprechen zurückgibt

Die Funktion aus meinem obigen Beispiel:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

gibt ein jqXHR-Objekt zurück, das ein jQuery Deferred Object ​​ist.

Um es zu einem echten Versprechen zu machen, können Sie es mit der Methode aus dem Q-Wiki in - ändern:

function testAjax() {
  return Q($.ajax({
      url: "getvalue.php"
  }));
}

oder mit die Methode aus dem HTML5 Rocks-Artikel :

function testAjax() {
  return Promise.resolve($.ajax({
      url: "getvalue.php"
  }));
}

Diese Promise.resolve($.ajax(...)) ist auch das, was in der promise Moduldokumentation erklärt ​​ist und mit ES6 Promise.resolve() funktionieren sollte.

Um die ES6 Promises heute zu nutzen, können Sie es6-promise module's polyfill() von Jake Archibald verwenden.

Informationen darüber, wo Sie die ES6-Versprechen ohne die Polyfüllung verwenden können, finden Sie unter: Kann ich verwenden: Versprechen .

Für weitere Informationen siehe:

Zukunft von jQuery

Zukünftige Versionen von jQuery (ab 3.x - aktuelle stabile Versionen ab Mai 2015 sind 1.x und 2.x) werden mit der Promises/A + -Spezifikation kompatibel sein (dank Benjamin Gruenbaum für den Hinweis in den Kommentaren). "Zwei Änderungen, für die wir uns bereits entschieden haben, sind Promise/A + -Kompatibilität für unsere verzögerte Implementierung [...]" ( jQuery 3.0 und die Zukunft der Webentwicklung ). Weitere Informationen finden Sie unter: jQuery 3.0: The Next Generations von Dave Methvin und jQuery 3.0: Mehr Interoperabilität, weniger Internet Explorer von Paul Krill.

Interessante Gespräche

UPDATE (2016)

Es gibt eine neue Syntax in ECMA-262, 6. Ausgabe, Abschnitt 14.2 mit dem Namen Pfeilfunktionen , die zur weiteren Vereinfachung der obigen Beispiele verwendet werden kann.

Verwenden der jQuery-API anstelle von:

promise.success(function (data) {
  alert(data);
});

du kannst schreiben:

promise.success(data => alert(data));

oder mit der Promises/A + API:

promise.then(data => alert(data));

Denken Sie daran, Ablehnungshandler immer zu verwenden, entweder mit:

promise.then(data => alert(data), error => alert(error));

oder mit:

promise.then(data => alert(data)).catch(error => alert(error));

Sehen Sie sich diese Antwort an, um herauszufinden, warum Sie immer Ablehnungshandler mit Versprechungen verwenden sollten:

Natürlich könnten Sie in diesem Beispiel nur promise.then(alert) verwenden, weil Sie alert mit denselben Argumenten aufrufen wie Ihr Rückruf, aber die Pfeilsyntax ist allgemeiner und ermöglicht Ihnen das Schreiben von Dingen wie:

promise.then(data => alert("x is " + data.x));

Nicht jeder Browser unterstützt diese Syntax, aber es gibt bestimmte Fälle, in denen Sie sicher sind, in welchem ​​Browser Ihr Code ausgeführt wird - z. Wenn Sie eine Chrome-Erweiterung , eine Firefox-Erweiterung oder eine Desktop-Anwendung mit Electron, NW.js oder AppJS schreiben (siehe diese Antwort ​​für Einzelheiten).

Informationen zur Unterstützung von Pfeilfunktionen finden Sie unter:

UPDATE (2017)

Derzeit gibt es eine noch neuere Syntax namens Async-Funktionen mit einem neuen await-Schlüsselwort, das anstelle des folgenden Codes verwendet wird:

functionReturningPromise()
    .then(data => console.log('Data:', data))
    .catch(error => console.log('Error:', error));

lässt dich schreiben:

try {
    let data = await functionReturningPromise();
    console.log('Data:', data);
} catch (error) {
    console.log('Error:', error);
}

Sie können es nur innerhalb einer Funktion verwenden, die mit dem Schlüsselwort async erstellt wurde. Weitere Informationen finden Sie unter:

Unterstützung in Browsern finden Sie unter:

Unterstützung in Node finden Sie unter:

An Orten, an denen Sie keine native Unterstützung für async und await haben, können Sie Babel verwenden:

oder mit einer etwas anderen Syntax einen generatorbasierten Ansatz wie in co oder Bluebird-Coroutinen:

Mehr Info

Einige andere Fragen zu Versprechungen für weitere Details:

387
rsp

sie können die Option async zu false hinzufügen nd außerhalb des Ajax-Aufrufs zurückkehren.

function testAjax() {
    var result="";
    $.ajax({
      url:"getvalue.php",
      async: false,  
      success:function(data) {
         result = data; 
      }
   });
   return result;
}
174
Ging3r

Idk, wenn ihr es gelöst habt, aber ich empfehle einen anderen Weg, und es funktioniert :)

    ServiceUtil = ig.Class.extend({
        base_url : 'someurl',

        sendRequest: function(request)
        {
            var url = this.base_url + request;
            var requestVar = new XMLHttpRequest();
            dataGet = false;

            $.ajax({
                url: url,
                async: false,
                type: "get",
                success: function(data){
                    ServiceUtil.objDataReturned = data;
                }
            });
            return ServiceUtil.objDataReturned;                
        }
    })

Die Hauptidee hier ist also, dass Sie durch Hinzufügen von async: false alles warten lassen, bis die Daten abgerufen werden. Dann weisen Sie es einer statischen Variablen der Klasse zu, und alles funktioniert auf magische Weise :)

0
user1509803