jQuery: Връщане на данни след успех на ajax повикването
Имам нещо подобно, което представлява просто извикване на скрипт, който ми връща стойност, низ.
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
return data;
}
});
}
но ако извикам нещо като това
var output = testAjax(svar); // output will be undefined...
как мога да върна стойността? изглежда, че и кодът по-долу не работи...
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
}
});
return data;
}
444
3
Забележка: Този отговор е написан през февруари 2010 г.
Вижте актуализациите от 2015 г., 2016 г. и 2017 г. в долната част. Не можете'да върнете нищо от функция, която е асинхронна. Това, което можете да върнете, е обещание. Обясних как работят обещанията в jQuery в отговорите си на тези въпроси:
можете да напишете функцията си testAjax по следния начин:
Тогава можете да получите обещанието си по следния начин:
Можете да съхранявате обещанието си, можете да го предавате, можете да го използвате като аргумент при извикване на функции и можете да го връщате от функции, но когато най-накрая искате да използвате данните си, върнати от AJAX извикването, трябва да го направите по следния начин:
(Вижте актуализациите по-долу за опростен синтаксис.) Ако данните ви са налични в този момент, тази функция ще бъде извикана незабавно. Ако не са, тогава тя ще бъде извикана веднага щом данните са налични. Смисълът на всичко това е, че данните ви не са налични веднага след извикването на $.ajax, защото то е асинхронно. Обещанията са хубава абстракция за функциите, които могат да кажат: Не мога да ви върна данните, защото все още не разполагам с тях, а не искам да блокирам и да ви карам да чакате, така че вместо това ви предлагам обещание, което ще можете да използвате по-късно, или просто да ги дадете на някой друг и да приключите с тях. Вижте това [DEMO](http://jsfiddle.net/jW68r/). UPDATE (2015 Г.)
Понастоящем (към март 2015 г.) jQuery Promises не са съвместими със спецификацията Promises/A+, което означава, че те може да не си сътрудничат много добре с други имплементации, съответстващи на Promises/A+. Въпреки това jQuery Promises в предстоящата версия 3.x ще бъдат съвместими със спецификацията Promises/A+ (благодаря на Benjamin Gruenbaum за това, че го посочи). Понастоящем (към май 2015 г.) стабилните версии на jQuery са 1.x и 2.x.
Това, което обясних по-горе (през март 2011 г.), е начин да се използват jQuery Deferred Objects, за да се направи нещо асинхронно, което в синхронен код би се постигнало чрез връщане на стойност. Но едно синхронно извикване на функция може да направи две неща - то може или да върне стойност (ако може), или да хвърли изключение (ако не може да върне стойност). Promises/A+ адресира и двата случая на употреба по начин, който е почти толкова мощен, колкото обработката на изключения в синхронен код. Версията на jQuery се справя отлично с еквивалента на връщане на стойност, но еквивалентът на сложна обработка на изключение е малко проблематичен. По-специално, целият смисъл на обработката на изключения в синхронен код не е просто да се откажеш с хубаво съобщение, а да се опиташ да решиш проблема и да продължиш изпълнението, или евентуално да хвърлиш отново същото или друго изключение, което да бъде обработено от други части на програмата. В синхронния код имате стек от повиквания. В асинхронното извикване нямате и усъвършенстваната обработка на изключенията вътре в обещанията ви, както се изисква от спецификацията Promises/A+, може наистина да ви помогне да напишете код, който ще обработва грешките и изключенията по смислен начин дори за сложни случаи на употреба. За разликите между jQuery и други имплементации и за това как да преобразувате обещанията на jQuery в съвместими с Promises/A+ вижте Coming from jQuery от Kris Kowal и др. в уикито на библиотеката Q и Promises arrive in JavaScript от Jake Archibald в HTML5 Rocks.
Как да върнем истинско обещание
Функцията от примера ми по-горе:
връща обект jqXHR, който е jQuery Deferred Object. За да я накарате да върне истинско обещание, можете да я промените на -, като използвате метода от уикипедия Q:
или, като използвате метода от статията HTML5 Rocks:
Този
Promise.resolve($.ajax(...))
също е това, което е обяснено в документацията на модулаpromise
и би трябвало да работи с ES6Promise.resolve()
. За да използвате ES6 Promises днес, можете да използвате es6-promise module'spolyfill()
на Jake Archibald. За да видите къде можете да използвате ES6 Promises без полифила, вижте: Мога ли да използвам: Promises. За повече информация вижте:Бъдещето на jQuery
Бъдещите версии на jQuery (като се започне от 3.x - настоящите стабилни версии към май 2015 г. са 1.x и 2.x) ще бъдат съвместими със спецификацията Promises/A+ (благодаря на Benjamin Gruenbaum за посочването ѝ в коментарите). "Две промени, които вече'сме решили, са съвместимост с Promise/A+ за нашата имплементация Deferred [...]" (jQuery 3.0 и бъдещето на уеб разработката). За повече информация вж: jQuery 3.0: Следващите поколения от Dave Methvin и jQuery 3.0: Повече оперативна съвместимост, по-малко Internet Explorer от Paul Krill.
Интересни разговори
[JavaScript Promises](https://youtu.be/oa2clhsYIDY) от Дейвид М. Лий (Nodevember 2014) UPDATE (2016)
В ECMA-262, 6th Edition, Section 14.2 има нов синтаксис, наречен arrow functions, който може да се използва за допълнително опростяване на горните примери. При използване на приложния програмен интерфейс jQuery, вместо:
можете да напишете:
или като използвате API Promises/A+:
Не забравяйте винаги да използвате обработчици за отхвърляне или с:
или с:
Вижте този отговор, за да разберете защо винаги трябва да използвате обработчици за отхвърляне с обещания:
promise.then(alert)
, защото просто извикватеalert
със същите аргументи като обратната връзка, но синтаксисът на стрелките е по-общ и ви позволява да пишете неща като:Все още не всеки браузър поддържа този синтаксис, но има някои случаи, когато сте сигурни на кой браузър ще работи кодът ви - например когато пишете разширение за Chrome, добавка за Firefox или десктоп приложение, използващо Electron, NW.js или AppJS (за подробности вижте този отговор). За поддръжката на функции със стрелки вижте:
await
, която вместо този код:ви позволява да напишете:
Можете да я използвате само вътре във функция, създадена с ключовата дума
async
. За повече информация вижте:async
иawait
, можете да използвате Babel:co
или Bluebird coroutines:http://bluebirdjs.com/docs/api/promise.coroutine.html Повече информация
Някои други въпроси за обещанията за повече подробности:
Единственият начин за връщане на данните от функцията би бил да се направи синхронно извикване вместо асинхронно, но това би замразило браузъра, докато чака отговора.
Можете да подадете функция за обратно извикване, която обработва резултата:
Извикайте я по следния начин:
Вижте примера в документацията на jquery: http://api.jquery.com/jQuery.ajax/ (около 2/3 от страницата)
Може би търсите следния код:
Същата страница... по-надолу.