531 Stimmen

jQuery: Rückgabe von Daten nach erfolgreichem Ajax-Aufruf

Ich habe etwas wie dieses, wo es einen einfachen Aufruf zu einem Skript, das mir einen Wert, eine Zeichenfolge zurückgibt ist.

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

aber wenn ich etwas wie dieses aufrufe

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

Wie kann ich also den Wert zurückgeben? der folgende Code scheint auch nicht zu funktionieren...

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

      }
   });
   return data; 
}

448voto

rsp Punkte 99616

Hinweis: Diese Antwort wurde im Februar 2010 verfasst.
Updates aus den Jahren 2015, 2016 und 2017 finden Sie am Ende der Seite.

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

Wenn Sie erklären könnten warum wollen Sie die Daten zurückgeben und was wollen Sie später damit machen, dann kann ich Ihnen vielleicht eine genauere Antwort geben, wie man es macht.

In der Regel anstelle von:

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

können Sie Ihre testAjax-Funktion wie folgt schreiben:

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

Dann können Sie Ihr Versprechen auf diese Weise einlösen:

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 wollen verwenden. Ihre Daten, die durch den AJAX-Aufruf zurückgegeben werden, müssen Sie wie folgt vorgehen:

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

(Für eine vereinfachte Syntax siehe unten.)

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

Der Sinn des Ganzen ist, dass Ihre Daten nicht sofort nach dem Aufruf von $.ajax zur Verfügung stehen, weil es asynchron ist. Promises ist eine schöne Abstraktion für Funktionen zu sagen: Ich kann dir die Daten nicht zurückgeben, weil ich sie noch nicht habe und ich will dich nicht blockieren und warten lassen, also hier ist ein Versprechen und Sie können es später verwenden oder es einfach jemand anderem geben und damit fertig werden.

Siehe dies DEMO .

UPDATE (2015)

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

Allerdings jQuery Promises in der kommenden Version 3.x wird mit der Promises/A+-Spezifikation kompatibel sein (dank der Benjamin Grünbaum für den Hinweis darauf). 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, die jQuery Aufgeschobene Objekte um asynchron etwas zu tun, was in synchronem Code durch die Rückgabe eines Wertes erreicht werden würde.

Ein synchroner Funktionsaufruf kann jedoch zwei Dinge tun - er kann entweder einen Wert zurückgeben (wenn er es kann) oder eine Ausnahme auslösen (wenn er keinen Wert zurückgeben kann). Promises/A+ adressiert beide Anwendungsfälle auf eine Art und Weise, die ziemlich genau so leistungsfähig ist wie die Ausnahmebehandlung in synchronem Code. Die jQuery-Version behandelt das Äquivalent der Rückgabe eines Wertes sehr gut, aber das Äquivalent der komplexen Ausnahmebehandlung ist etwas problematisch.

Insbesondere geht es bei der Behandlung von Ausnahmen in synchronem Code nicht darum, einfach mit einer netten Meldung aufzugeben, sondern zu versuchen, das Problem zu beheben und die Ausführung fortzusetzen oder möglicherweise die gleiche oder eine andere Ausnahme für andere Teile des Programms erneut auszulösen. In synchronem Code haben Sie einen Aufrufstapel. Bei asynchronen Aufrufen ist das nicht der Fall, und eine fortgeschrittene Ausnahmebehandlung innerhalb Ihrer Promises, wie sie von der Promises/A+-Spezifikation gefordert wird, kann Ihnen wirklich dabei helfen, Code zu schreiben, der Fehler und Ausnahmen auf sinnvolle Weise behandelt, selbst bei komplexen Anwendungsfällen.

Zu den Unterschieden zwischen jQuery und anderen Implementierungen und zur Konvertierung von jQuery-Promises in Promises/A+-konforme Promises, siehe Von jQuery kommend von Kris Kowal et al. auf dem Q library wiki und Versprechen kommen in JavaScript 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 Zurückgestelltes Objekt .

Damit es ein echtes Versprechen zurückgibt, können Sie es in - ändern, indem Sie die Methode aus dem Q-Wiki :

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

oder über die Methode aus dem Artikel HTML5 Rocks :

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

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

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

Um zu sehen, wo Sie die ES6 Promises ohne das Polyfill verwenden können, siehe: Kann ich verwenden: Versprechen .

Für weitere Informationen siehe:

Die 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 dem Versprechen/A+ Spezifikation (Dank an Benjamin Grünbaum dass Sie in den Kommentaren darauf hingewiesen haben). "Zwei Änderungen, die wir bereits beschlossen haben, sind Promise/A+ Kompatibilität für unsere Deferred Implementierung [...]" ( jQuery 3.0 und die Zukunft der Webentwicklung ). Für weitere Informationen siehe: jQuery 3.0: Die nächsten Generationen 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. Auflage, Abschnitt 14.2 genannt. Pfeilfunktionen die zur weiteren Vereinfachung der obigen Beispiele verwendet werden können.

Verwendung der jQuery-API, statt:

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

können Sie schreiben:

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

oder unter Verwendung der Promises/A+-API:

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

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

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

oder mit:

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

In dieser Antwort erfahren Sie, warum Sie bei Versprechen immer Ablehnungshandler verwenden sollten:

Natürlich könnte man in diesem Beispiel auch nur promise.then(alert) denn du rufst nur alert mit denselben Argumenten wie Ihr Rückruf, aber die Pfeil-Syntax ist allgemeiner und ermöglicht es Ihnen, Dinge zu schreiben wie:

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

Noch unterstützt nicht jeder Browser diese Syntax, aber es gibt bestimmte Fälle, in denen Sie sicher sind, in welchem Browser Ihr Code laufen wird - z.B. beim Schreiben einer Chrome-Erweiterung , a Firefox-Zusatzmodul oder eine Desktop-Anwendung mit Electron, NW.js oder AppJS (siehe diese Antwort für Details).

Für die Unterstützung von Pfeilfunktionen, siehe:

UPDATE (2017)

Es gibt jetzt eine noch neuere Syntax namens async-Funktionen mit einer neuen await Schlüsselwort anstelle dieses Codes:

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

lässt Sie schreiben:

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

Sie können ihn nur innerhalb einer Funktion verwenden, die mit der Option async Stichwort. Für weitere Informationen siehe:

Für die Unterstützung in Browsern, siehe:

Für Unterstützung in Node, siehe:

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

oder mit einer etwas anderen Syntax ein generatorbasierter Ansatz wie in co oder Bluebird-Koroutinen:

Mehr Infos

Einige andere Fragen zu Versprechen für mehr Details:

425voto

Guffa Punkte 663241

Die einzige Möglichkeit, die Daten aus der Funktion zurückzugeben, bestünde darin, einen synchronen Aufruf anstelle eines asynchronen Aufrufs zu machen, aber das würde den Browser einfrieren, während er auf die Antwort wartet.

Sie können eine Callback-Funktion übergeben, die das Ergebnis verarbeitet:

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

Sagen wir 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.

219voto

Ging3r Punkte 2825

Können Sie die Option async auf false setzen et außerhalb des Ajax-Aufrufs zurückgeben.

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

0voto

user1509803 Punkte 186

Ich weiß nicht, ob ihr das Problem 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;                
        }
    })

Der Grundgedanke dabei ist, dass Sie durch Hinzufügen von async: false alles so lange warten lassen, bis die Daten abgerufen werden. Dann weisen Sie sie einer statischen Variablen der Klasse zu, und alles funktioniert auf magische Weise :)

-15voto

Techism Punkte 532

Siehe jquery docs Beispiel: http://api.jquery.com/jQuery.ajax/ (etwa 2/3 der Seite)

Sie können nach folgendem Code suchen:

    $.ajax({
     url: 'ajax/test.html',
     success: function(data) {
     $('.result').html(data);
     alert('Load was performed.');
   }
});

Dieselbe Seite...weiter unten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X