Więcej
jQuery: Zwróć dane po sukcesie wywołania ajaxowego
Mam coś takiego, gdzie jest to proste wywołanie do skryptu, który zwraca mi wartość, ciąg...
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
return data;
}
});
}
ale jeśli wywołam coś takiego jak to
var output = testAjax(svar); // output will be undefined...
więc jak mogę zwrócić wartość? poniższy kod również nie wydaje się działać...
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
}
});
return data;
}
444
3
Uwaga: Ta odpowiedź została napisana w lutym 2010 roku.
Zobacz aktualizacje z 2015, 2016 i 2017 roku na dole. Nie możesz'zwrócić niczego z funkcji, która jest asynchroniczna. To, co możesz zwrócić, to obietnica. Wyjaśniłem, jak obietnice działają w jQuery w moich odpowiedziach na te pytania:
możesz napisać swoją funkcję testAjax w ten sposób:
Następnie możesz uzyskać swoją obietnicę w ten sposób:
Możesz przechowywać swoją obietnicę, możesz ją przekazywać, możesz używać jej jako argumentu w wywołaniach funkcji i możesz ją zwracać z funkcji, ale kiedy w końcu chcesz używać swoich danych, które są zwracane przez wywołanie AJAX, musisz to zrobić w ten sposób:
(Zobacz aktualizacje poniżej dla uproszczonej składni.). Jeśli Twoje dane są dostępne w tym momencie, wtedy ta funkcja zostanie wywołana natychmiast. Jeśli nie, to zostanie ona wywołana, gdy tylko dane będą dostępne. Cały sens robienia tego wszystkiego polega na tym, że twoje dane nie są dostępne natychmiast po wywołaniu $.ajax, ponieważ jest to funkcja asynchroniczna. Obietnice są miłą abstrakcją dla funkcji, aby powiedzieć: I can't return you the data because I don't have it yet and I don't want to block and make you wait so here's a promise instead and you'll be able to use it later, or to just give it to someone else and be done with it. Zobacz to [DEMO](http://jsfiddle.net/jW68r/). UPDATE (2015)
Obecnie (stan na marzec, 2015) jQuery Promises nie są zgodne ze specyfikacją Promises/A+, co oznacza, że mogą nie współpracować zbyt dobrze z innymi implementacjami Promises/A+ conformant. Jednak jQuery Promises w nadchodzącej wersji 3.x będzie zgodne ze specyfikacją Promises/A+ (podziękowania dla Benjamina Gruenbauma za zwrócenie na to uwagi). Obecnie (stan na maj, 2015) stabilne wersje jQuery to 1.x i 2.x.
To, co wyjaśniłem powyżej (w marcu, 2011) jest sposobem na użycie jQuery Deferred Objects do zrobienia czegoś asynchronicznie, co w kodzie synchronicznym zostałoby osiągnięte przez zwrócenie wartości. Ale synchroniczne wywołanie funkcji może zrobić dwie rzeczy - może albo zwrócić wartość (jeśli może) albo rzucić wyjątek (jeśli nie może'zwrócić wartości). Promises/A+ zajmuje się oboma tymi przypadkami użycia w sposób, który jest dość potężny jak obsługa wyjątków w kodzie synchronicznym. Wersja jQuery obsługuje odpowiednik zwracania wartości po prostu dobrze, ale odpowiednik złożonej obsługi wyjątków jest nieco problematyczny. W szczególności, całym sensem obsługi wyjątków w kodzie synchronicznym nie jest po prostu rezygnacja z miłą wiadomością, ale próba naprawienia problemu i kontynuowania wykonywania, lub ewentualnie ponowne rzucenie tego samego lub innego wyjątku dla innych części programu do obsługi. W kodzie synchronicznym masz stos wywołań. W kodzie asynchronicznym nie, a zaawansowana obsługa wyjątków wewnątrz obietnic, zgodnie ze specyfikacją Promises/A+, może naprawdę pomóc w pisaniu kodu, który będzie obsługiwał błędy i wyjątki w znaczący sposób, nawet dla złożonych przypadków użycia. O różnicach między jQuery a innymi implementacjami oraz o tym, jak przekonwertować obietnice jQuery na zgodne z Promises/A+, zobacz Coming from jQuery autorstwa Krisa Kowala et al. na wiki biblioteki Q oraz Promises arrive in JavaScript autorstwa Jake'a Archibalda na HTML5 Rocks.
Jak zwrócić prawdziwą obietnicę
Funkcja z mojego przykładu powyżej:
zwraca obiekt jqXHR, który jest jQuery Deferred Object. Aby zwrócić prawdziwą obietnicę, możesz zmienić ją na - używając metody z wiki Q:
lub, używając metody z artykułu HTML5 Rocks:
To
Promise.resolve($.ajax(...))
jest również tym, co jest wyjaśnione w dokumentacji modułupromise
i powinno działać z ES6Promise.resolve()
. Aby używać obietnic ES6 dzisiaj, możesz użyć es6-promise module'spolyfill()
Jake'a Archibalda. Aby zobaczyć, gdzie możesz użyć ES6 Promises bez polyfill, zobacz: Can I use: Promises. Aby uzyskać więcej informacji zobacz:Przyszłość jQuery
Przyszłe wersje jQuery (począwszy od 3.x - obecne stabilne wersje na maj 2015 to 1.x i 2.x) będą zgodne ze specyfikacją Promises/A+ (podziękowania dla Benjamina Gruenbauma za wskazanie jej w komentarzach). "Dwie zmiany, na które już się zdecydowaliśmy, to zgodność z Promise/A+ dla naszej implementacji Deferred [...]" (jQuery 3.0 i przyszłość tworzenia stron internetowych). Więcej informacji można znaleźć w: jQuery 3.0: The Next Generations autorstwa Dave'a Methvina oraz jQuery 3.0: More interoperability, less Internet Explorer autorstwa Paula Krilla.
Ciekawe rozmowy
[Obietnice JavaScript](https://youtu.be/oa2clhsYIDY) by David M. Lee (Nodevember 2014) UPDATE (2016)
Istnieje nowa składnia w ECMA-262, 6th Edition, Section 14.2 zwana arrow functions, która może być użyta do dalszego uproszczenia powyższych przykładów. Używając API jQuery, zamiast:
można napisać:
lub korzystając z API Promises/A+:
Pamiętaj, aby zawsze używać handlerów odrzuceń albo z:
lub z:
Zobacz tę odpowiedź, aby zobaczyć, dlaczego zawsze powinieneś używać handlarzy odrzuceniem z obietnicami:
promise.then(alert)
, ponieważ ty're po prostu wywołaniealert
z tymi samymi argumentami, co twój callback, ale składnia strzałki jest bardziej ogólna i pozwala pisać rzeczy takie jak:Nie każda przeglądarka obsługuje tę składnię, ale są pewne przypadki, kiedy jesteś pewien, na jakiej przeglądarce będzie działać twój kod - np. kiedy piszesz Chrome extension, Firefox Add-on, lub aplikację desktopową używającą Electron, NW.js lub AppJS (zobacz ta odpowiedź po szczegóły). Aby uzyskać wsparcie dla funkcji strzałek, zobacz:
await
, które zamiast tego kodu:pozwala napisać:
Możesz go użyć tylko wewnątrz funkcji utworzonej za pomocą słowa kluczowego
async
. Aby uzyskać więcej informacji, zobacz:async
iawait
możesz użyć Babel:co
lub Bluebird coroutines:http://bluebirdjs.com/docs/api/promise.coroutine.html Więcej informacji
Kilka innych pytań na temat obietnic, aby uzyskać więcej szczegółów:
Jedynym sposobem na zwrócenie danych z funkcji byłoby wykonanie wywołania synchronicznego zamiast asynchronicznego, ale to spowodowałoby zamrożenie przeglądarki podczas oczekiwania na odpowiedź.
Możesz przekazać funkcję wywołania zwrotnego, która obsłuży wynik:
Wywołaj ją w ten sposób:
Zobacz przykład w jquery docs: http://api.jquery.com/jQuery.ajax/ (około 2/3 strony)
Być może będziesz szukał następującego kodu:
Ta sama strona...niżej.