Lisää
jQuery: Palauta tiedot ajax-kutsun onnistumisen jälkeen
Minulla on jotain tällaista, jossa on yksinkertainen kutsu skriptiin, joka antaa minulle takaisin arvon, merkkijonon...
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
return data;
}
});
}
mutta jos kutsun jotain tällaista
var output = testAjax(svar); // output will be undefined...
niin miten voin palauttaa arvon? myöskään alla oleva koodi ei näytä toimivan...
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
}
});
return data;
}
444
3
Huom: Tämä vastaus on kirjoitettu helmikuussa 2010.
Katso päivitykset vuosilta 2015, 2016 ja 2017 alareunasta. Asynkronisesta funktiosta ei voi palauttaa mitään. Se, mitä voit palauttaa, on lupaus. Selitin vastauksissani näihin kysymyksiin, miten lupaukset toimivat jQueryssä:
voit kirjoittaa testAjax-funktion näin:
Sitten saat lupauksesi näin:
Voit tallentaa lupauksesi, voit välittää sen eteenpäin, voit käyttää sitä argumenttina funktiokutsuissa ja voit palauttaa sen funktioista, mutta kun lopulta haluat käyttää AJAX-kutsun palauttamia tietojasi, sinun on tehtävä se näin:
(Yksinkertaistettu syntaksi on päivityksissä alla.) Jos tietosi ovat käytettävissä tässä vaiheessa, tämä funktio kutsutaan välittömästi. Jos se ei ole, se kutsutaan heti, kun tiedot ovat saatavilla. Koko tämän tekemisen tarkoitus on, että tietosi eivät ole käytettävissä heti $.ajax-kutsun jälkeen, koska se on asynkroninen. Lupaukset on mukava abstraktio funktioille sanoa: En voi palauttaa sinulle dataa, koska minulla ei ole sitä vielä, enkä halua estää sinua odottamasta, joten tässä on sen sijaan lupaus, jonka avulla voit käyttää sitä myöhemmin, tai antaa sen jollekin toiselle ja hoitaa asian. Katso tämä [DEMO](http://jsfiddle.net/jW68r/). PÄIVITYS (2015)
Tällä hetkellä (maaliskuussa 2015) jQuery Promises ei ole yhteensopiva Promises/A+ -spesifikaation kanssa, mikä tarkoittaa, että ne eivät välttämättä toimi kovin hyvin yhteistyössä muiden Promises/A+ -yhteensopivien toteutusten kanssa. Tulevassa versiossa 3.x jQuery Promises tulee kuitenkin olemaan yhteensopiva Promises/A+-spesifikaation kanssa (kiitos Benjamin Gruenbaumille, joka huomautti asiasta). Tällä hetkellä (toukokuussa 2015) jQueryn vakaat versiot ovat 1.x ja 2.x.
Edellä (maaliskuussa 2011) selitin, että jQuery Deferred Objects on tapa käyttää jQuery Deferred Objects tekemään asynkronisesti jotakin, joka synkronisessa koodissa saavutettaisiin palauttamalla arvo. Mutta synkroninen funktiokutsu voi tehdä kaksi asiaa - se voi joko palauttaa arvon (jos se voi) tai heittää poikkeuksen (jos se ei voi palauttaa arvoa). Promises/A+ ratkaisee molemmat näistä käyttötapauksista tavalla, joka on melko lailla yhtä tehokas kuin poikkeusten käsittely synkronisessa koodissa. JQuery-versio käsittelee arvon palauttamista vastaavan tehtävän hienosti, mutta monimutkaisten poikkeusten käsittely on hieman ongelmallista. Poikkeuskäsittelyn tarkoitus synkronisessa koodissa ei ole vain luovuttaa mukavan viestin kanssa, vaan yrittää korjata ongelma ja jatkaa suoritusta tai mahdollisesti heittää sama tai erilainen poikkeus uudelleen ohjelman muiden osien käsiteltäväksi. Synkronisessa koodissa on kutsupino. Asynkronisessa kutsussa sitä ei ole, ja Promises/A+ -spesifikaation edellyttämä kehittynyt poikkeuskäsittely lupausten sisällä voi todella auttaa sinua kirjoittamaan koodia, joka käsittelee virheet ja poikkeukset mielekkäällä tavalla myös monimutkaisissa käyttötapauksissa. Erilaisuuksista jQueryn ja muiden toteutusten välillä sekä siitä, miten jQueryn lupaukset muunnetaan Promises/A+-yhteensopiviksi, on kerrottu Kris Kowalin ym. artikkelissa Coming from jQuery Q-kirjaston wikissä ja Jake Archibaldin artikkelissa Promises arrive in JavaScript HTML5 Rocksissa.
Miten palauttaa oikea lupaus
Yllä olevan esimerkkini funktio:
palauttaa jqXHR-olion, joka on jQueryn Deferred Object. Jotta se palauttaisi todellisen lupauksen, voit muuttaa sen muotoon - käyttämällä Q-wikin metodia:
tai käyttämällä HTML5 Rocks -artikkelin metodia:
Tämä
Promise.resolve($.ajax(...))
on myös se, mitä selitetäänpromise
-moduulin dokumentaatiossa ja sen pitäisi toimia ES6Promise.resolve()
kanssa. Jos haluat käyttää ES6-lupauksia nykyään, voit käyttää es6-promise-moduuli'npolyfill()
Jake Archibaldin tekemää es6-promise-moduuli'npolyfill()
. Jos haluat nähdä, missä voit käyttää ES6 Promisesia ilman polyfilliä, katso: Can I use: Promises. Lisätietoja on osoitteessa:jQueryn tulevaisuus
Tulevat jQueryn versiot (3.x:stä alkaen - nykyiset vakaat versiot toukokuussa 2015 ovat 1.x ja 2.x) ovat yhteensopivia Promises/A+-määrittelyn kanssa (kiitos Benjamin Gruenbaumille, joka huomautti asiasta kommenteissa). "Kaksi muutosta, joista olemme jo päättäneet, ovat Promise/A+-yhteensopivuus Deferred-toteutuksellemme [...]" (jQuery 3.0 and the future of Web development). Lisätietoja on osoitteessa: jQuery 3.0: The Next Generations, kirjoittanut Dave Methvin ja jQuery 3.0: More interoperability, less Internet Explorer, kirjoittanut Paul Krill.
Mielenkiintoisia keskusteluja
[JavaScript Promises](https://youtu.be/oa2clhsYIDY) kirjoittanut David M. Lee (Nodevember 2014) PÄIVITYS (2016)
Teoksessa ECMA-262, 6th Edition, Section 14.2 on uusi syntaksi nimeltä arrow functions, jota voidaan käyttää yllä olevien esimerkkien yksinkertaistamiseen edelleen. Käyttämällä jQuery API:ta sen sijaan, että:
voit kirjoittaa:
tai käyttämällä Promises/A+ API:ta:
Muista aina käyttää hylkäyskäsittelijöitä joko:
tai kanssa:
Katso tästä vastauksesta, miksi hylkäyskäsittelijöitä kannattaa aina käyttää lupausten kanssa:
promise.then(alert)
, koska kutsut vainalert
samoilla argumenteilla kuin takaisinsoittosi, mutta nuoli-syntaksi on yleisempi ja sen avulla voit kirjoittaa esimerkiksi:Kaikki selaimet eivät vielä tue tätä syntaksia, mutta on tiettyjä tapauksia, joissa olet varma, millä selaimella koodisi toimii - esimerkiksi kirjoittaessasi Chrome-laajennusta, Firefox-lisäosaa tai työpöytäsovellusta, jossa käytetään Electronia, NW.js:ää tai AppJS:ää (katso lisätietoja tästä vastauksesta). Nuolifunktioiden tuesta ks:
await
-avainsana, joka tämän koodin sijaan:voit kirjoittaa:
Voit käyttää sitä vain
async
-avainsanalla luodun funktion sisällä. Lisätietoja on osoitteessa:async
:lle jaawait
:lle, voit käyttää Babelia:co
:ssa tai Bluebird-korutiineissa:http://bluebirdjs.com/docs/api/promise.coroutine.html Lisätietoja
Joitakin muita kysymyksiä lupauksista lisätietoja varten:
Ainoa tapa palauttaa tiedot funktiosta olisi tehdä synkroninen kutsu asynkronisen kutsun sijasta, mutta se jähmettäisi selaimen odottaessaan vastausta.
Voit välittää takaisinsoittofunktion, joka käsittelee tuloksen:
Kutsu sitä näin:
Katso jquery docs -esimerkki: http://api.jquery.com/jQuery.ajax/ (noin 2/3 sivusta)
Saatat etsiä seuraavaa koodia:
Sama sivu... alempana.