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;
}
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:
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
return data;
}
});
}
môžete svoju funkciu testAjax napísať takto:
function testAjax() {
return $.ajax({
url: "getvalue.php"
});
}
Potom môžete získať svoj prísľub takto:
var promise = testAjax();
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:
promise.success(function (data) {
alert(data);
});
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.
Funkcia z môjho príkladu vyššie:
function testAjax() {
return $.ajax({
url: "getvalue.php"
});
}
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:
function testAjax() {
return Q($.ajax({
url: "getvalue.php"
}));
}
alebo pomocou metódy z článku HTML5 Rocks:
function testAjax() {
return Promise.resolve($.ajax({
url: "getvalue.php"
}));
}
Tento Promise.resolve($.ajax(...))
je tiež to, čo je vysvetlené v dokumentácii modulu promise
a malo by to fungovať s ES6 Promise.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ú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.
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:
promise.success(function (data) {
alert(data);
});
môžete napísať:
promise.success(data => alert(data));
alebo pomocou API Promises/A+:
promise.then(data => alert(data));
Nezabudnite vždy používať obsluhy odmietnutia buď s:
promise.then(data => alert(data), error => alert(error));
alebo s:
promise.then(data => alert(data)).catch(error => alert(error));
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áte alert
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:promise.then(data => alert("x is " + data.x));
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:functionReturningPromise()
.then(data => console.log('Data:', data))
.catch(error => console.log('Error:', error));
umožňuje napísať:
try {
let data = await functionReturningPromise();
console.log('Data:', data);
} catch (error) {
console.log('Error:', error);
}
Môžete ho použiť len vo vnútri funkcie vytvorenej pomocou kľúčového slova async
. Viac informácií nájdete na:
async
a await
, môžete použiť Babel:co
alebo Bluebird coroutines: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:
function testAjax(handleData) {
$.ajax({
url:"getvalue.php",
success:function(data) {
handleData(data);
}
});
}
Volajte ju takto:
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.
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:
$.ajax({
url: 'ajax/test.html',
success: function(data) {
$('.result').html(data);
alert('Load was performed.');
}
});
Tá istá stránka... nižšie.