Viac na
jQuery: Vrátenie údajov po úspešnom ajaxovom volaní
Mám niečo podobné, kde je jednoduché volanie skriptu, ktorý mi vráti hodnotu, reťazec.
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
return data;
}
});
}
ale ak zavolám niečo také
var output = testAjax(svar); // output will be undefined...
tak ako môžem vrátiť hodnotu? zdá sa, že ani nižšie uvedený kód nefunguje...
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
}
});
return data;
}
444
3
Poznámka: Táto odpoveď bola napísaná vo februári 2010.
Pozrite si aktualizácie z rokov 2015, 2016 a 2017 na konci článku. Z funkcie, ktorá je asynchrónna, nemôžete'nič vrátiť. To, čo môžete vrátiť, je prísľub. Ako fungujú sľuby v jQuery, som vysvetlil v odpovediach na tieto otázky:
môžete svoju funkciu testAjax napísať takto:
Potom môžete získať svoj prísľub takto:
Svoj prísľub môžete uložiť, môžete ho posielať ďalej, môžete ho použiť ako argument vo volaniach funkcií a môžete ho vrátiť z funkcií, ale keď chcete konečne použiť svoje údaje, ktoré sa vrátia z volania AJAX, musíte to urobiť takto:
(Zjednodušenú syntax nájdete v aktualizáciách nižšie.) Ak sú vaše údaje v tomto okamihu k dispozícii, potom sa táto funkcia vyvolá okamžite. Ak nie sú, potom sa vyvolá hneď, ako budú údaje k dispozícii. Celý zmysel tohto všetkého spočíva v tom, že vaše údaje nie sú k dispozícii okamžite po volaní $.ajax, pretože je asynchrónny. Prísľuby sú peknou abstrakciou pre funkcie, ktoré sa dajú povedať: Nemôžem vám vrátiť údaje, pretože ich ešte nemám a nechcem ich blokovať a nechať vás čakať, takže namiesto toho tu máte prísľub a budete ich môcť použiť neskôr, alebo ich jednoducho dať niekomu inému a skončiť s tým. Pozri tento [DEMO](http://jsfiddle.net/jW68r/). UPDATE (2015)
V súčasnosti (od marca 2015) nie sú jQuery Promises kompatibilné so špecifikáciou Promises/A+, čo znamená, že nemusia veľmi dobre spolupracovať s inými implementáciami vyhovujúcimi Promises/A+. Avšak jQuery Promises v nadchádzajúcej verzii 3.x budú kompatibilné so špecifikáciou Promises/A+ (vďaka Benjaminovi Gruenbaumovi za upozornenie). V súčasnosti (od mája 2015) sú stabilné verzie jQuery 1.x a 2.x.
To, čo som vysvetlil vyššie (v marci 2011), je spôsob, ako použiť jQuery Deferred Objects na asynchrónne vykonanie niečoho, čo by sa v synchrónnom kóde dosiahlo vrátením hodnoty. Synchrónne volanie funkcie však môže urobiť dve veci - buď vráti hodnotu (ak ju môže vrátiť), alebo vyhodí výnimku (ak hodnotu vrátiť nemôže). Promises/A+ rieši oba tieto prípady použitia spôsobom, ktorý je v podstate rovnako výkonný ako spracovanie výnimiek v synchrónnom kóde. Verzia jQuery zvláda ekvivalent vrátenia hodnoty v poriadku, ale ekvivalent komplexného spracovania výnimiek je trochu problematický. Celý zmysel spracovania výnimiek v synchrónnom kóde nespočíva najmä v tom, že sa len vzdá s peknou správou, ale snaží sa problém odstrániť a pokračovať vo vykonávaní, prípadne znovu vyhodiť tú istú alebo inú výnimku, ktorú majú spracovať iné časti programu. V synchrónnom kóde máte zásobník volaní. V asynchrónnom volaní ho nemáte'a pokročilé spracovanie výnimiek vo vnútri sľubov, ako to vyžaduje špecifikácia Promises/A+, vám môže skutočne pomôcť napísať kód, ktorý bude zmysluplne spracovávať chyby a výnimky aj pre zložité prípady použitia. Rozdiely medzi jQuery a inými implementáciami a spôsob konverzie sľubov jQuery na sľuby vyhovujúce špecifikácii Promises/A+ nájdete v publikáciách Coming from jQuery od Krisa Kovala a ďalších na wiki knižnice Q a Promises arrive in JavaScript od Jakea Archibalda na HTML5 Rocks.
Ako vrátiť skutočný sľub
Funkcia z môjho príkladu vyššie:
vráti objekt jqXHR, čo je jQuery Deferred Object. Ak chcete, aby vrátila skutočný sľub, môžete ho zmeniť na - pomocou metódy z Q wiki:
alebo pomocou metódy z článku HTML5 Rocks:
Tento
Promise.resolve($.ajax(...))
je tiež to, čo je vysvetlené v dokumentácii modulupromise
a malo by to fungovať s ES6Promise.resolve()
. Na použitie ES6 Promises dnes môžete použiť es6-promise modul'polyfill()
od Jakea Archibalda. Ak chcete zistiť, kde môžete použiť ES6 Promises bez polyfill, pozrite si: Can I use: Promises. Ďalšie informácie nájdete na stránke:Budúcnosť jQuery
Budúce verzie jQuery (počnúc verziou 3.x - aktuálne stabilné verzie z mája 2015 sú 1.x a 2.x) budú kompatibilné so špecifikáciou Promises/A+ (vďaka Benjaminovi Gruenbaumovi za upozornenie v komentároch). "Dve zmeny, o ktorých sme'už rozhodli, sú kompatibilita so špecifikáciou Promise/A+ pre našu implementáciu Deferred [...]" (jQuery 3.0 a budúcnosť vývoja webu). Viac informácií nájdete na stránke: jQuery 3.0: The Next Generations od Davea Methvina a jQuery 3.0: Viac interoperability, menej Internet Explorera od Paula Krilla.
Zaujímavé rozhovory
[JavaScript Promises](https://youtu.be/oa2clhsYIDY) od Davida M. Lee (Nodevember 2014) UPDATE (2016)
V ECMA-262, 6. vydanie, časť 14.2 je nová syntax s názvom arrow functions, ktorú možno použiť na ďalšie zjednodušenie uvedených príkladov. Pri použití rozhrania jQuery API namiesto:
môžete napísať:
alebo pomocou API Promises/A+:
Nezabudnite vždy používať obsluhy odmietnutia buď s:
alebo s:
V tejto odpovedi sa dozviete, prečo by ste mali vždy používať obsluhy odmietnutia s prísľubmi:
promise.then(alert)
, pretože len volátealert
s rovnakými argumentmi ako vaše spätné volanie, ale syntax šípky je všeobecnejšia a umožňuje vám napísať veci ako napr:Túto syntax zatiaľ nepodporujú všetky prehliadače, ale existujú určité prípady, keď'ste si istí, v akom prehliadači bude váš kód bežať - napr. pri písaní rozšírenia pre Chrome, doplnku pre Firefox alebo desktopovej aplikácie pomocou Electronu, NW.js alebo AppJS (podrobnosti nájdete v tejto odpovedi). Pokiaľ ide o podporu šípkových funkcií, pozrite si:
await
, ktoré namiesto tohto kódu:umožňuje napísať:
Môžete ho použiť len vo vnútri funkcie vytvorenej pomocou kľúčového slova
async
. Viac informácií nájdete na:async
aawait
, môžete použiť Babel:co
alebo Bluebird coroutines:http://bluebirdjs.com/docs/api/promise.coroutine.html Viac informácií
Niektoré ďalšie otázky o sľuboch pre viac informácií:
Jediný spôsob, ako vrátiť údaje z funkcie, by bolo synchrónne volanie namiesto asynchrónneho volania, ale to by prehliadač počas čakania na odpoveď zamrzol.
Môžete odovzdať funkciu spätného volania, ktorá spracuje výsledok:
Volajte ju takto:
Pozrite si príklad v dokumentoch jquery: http://api.jquery.com/jQuery.ajax/ (asi 2/3 stránky)
Možno hľadáte nasledujúci kód:
Tá istá stránka... nižšie.