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: