Tengo algo así, donde es una simple llamada a un script que me devuelve un valor, una cadena..
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
return data;
}
});
}
pero si llamo a algo como esto
var output = testAjax(svar); // output will be undefined...
¿cómo puedo devolver el valor? el código de abajo tampoco parece funcionar...
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
}
});
return data;
}
**Nota: Esta respuesta fue escrita en febrero de 2010. Vea las actualizaciones de 2015, 2016 y 2017 en la parte inferior. No se puede devolver nada de una función que es asíncrona. Lo que puedes devolver es una promesa*. Ya expliqué cómo funcionan las promesas en jQuery en mis respuestas a esas preguntas:
function testAjax() {
$.ajax({
url: "getvalue.php",
success: function(data) {
return data;
}
});
}
puedes escribir tu función testAjax así
function testAjax() {
return $.ajax({
url: "getvalue.php"
});
}
Entonces puedes obtener tu promesa así
var promise = testAjax();
Puedes almacenar tu promesa, puedes pasarla, puedes usarla como argumento en las llamadas a funciones y puedes devolverla desde las funciones, pero cuando finalmente quieras utilizar tus datos devueltos por la llamada AJAX, tienes que hacerlo así:
promise.success(function (data) {
alert(data);
});
Actualmente (en marzo de 2015) jQuery Promises no es compatible con la especificación Promises/A+ lo que significa que puede no cooperar muy bien con otras implementaciones conformes a Promises/A+. Sin embargo, jQuery Promises en la próxima versión 3.x será compatible con la especificación Promises/A+ (gracias a Benjamin Gruenbaum por señalarlo). Actualmente (en mayo de 2015) las versiones estables de jQuery son la 1.x y la 2.x.
Lo que expliqué arriba (en marzo de 2011) es una forma de usar jQuery Deferred Objects para hacer algo de forma asíncrona que en código síncrono se conseguiría devolviendo un valor. Pero una llamada a una función sincrónica puede hacer dos cosas - puede devolver un valor (si puede) o lanzar una excepción (si no puede devolver un valor). Promises/A+ aborda ambos casos de uso de una forma tan potente como el manejo de excepciones en el código síncrono. La versión de jQuery maneja muy bien el equivalente a devolver un valor, pero el equivalente al manejo de excepciones complejas es algo problemático. En particular, el objetivo del manejo de excepciones en código síncrono no es simplemente rendirse con un bonito mensaje, sino intentar arreglar el problema y continuar la ejecución, o posiblemente volver a lanzar la misma excepción o una diferente para que otras partes del programa la manejen. En el código síncrono tienes una pila de llamadas. En el código asíncrono no, y el manejo avanzado de excepciones dentro de las promesas, tal y como lo requiere la especificación Promises/A+, puede ayudarte a escribir código que maneje los errores y las excepciones de manera significativa, incluso para casos de uso complejos. Para conocer las diferencias entre jQuery y otras implementaciones, y cómo convertir las promesas de jQuery en compatibles con Promises/A+, véase Coming from jQuery por Kris Kowal et al. en el wiki de la biblioteca Q y Promises arrive in JavaScript por Jake Archibald en HTML5 Rocks.
La función de mi ejemplo anterior:
function testAjax() {
return $.ajax({
url: "getvalue.php"
});
}
devuelve un objeto jqXHR, que es un [Deferred Object] de jQuery (https://api.jquery.com/category/deferred-object/). Para que devuelva una promesa real, puedes cambiarla por - usando el método de la wiki de Q:
function testAjax() {
return Q($.ajax({
url: "getvalue.php"
}));
}
o, usando el método del artículo HTML5 Rocks:
function testAjax() {
return Promise.resolve($.ajax({
url: "getvalue.php"
}));
}
Esta Promise.resolve($.ajax(...))
es también lo que está explicado en la documentación del módulo promise
y debería funcionar con ES6 Promise.resolve()
.
Para utilizar las promesas de ES6 hoy en día puedes utilizar es6-promise module's polyfill()
de Jake Archibald.
Para ver dónde puede usar las Promesas ES6 sin el polyfill, vea: Puedo usar: Promises.
Para más información, consulte:
Las futuras versiones de jQuery (a partir de la 3.x - las versiones estables actuales a partir de mayo de 2015 son la 1.x y la 2.x) serán compatibles con la especificación Promises/A+ (gracias a Benjamin Gruenbaum por señalarlo en los comentarios). "Dos cambios que ya hemos decidido son la compatibilidad con Promise/A+ para nuestra implementación Deferred [...]" (jQuery 3.0 y el futuro del desarrollo web). Para más información, consulte: jQuery 3.0: The Next Generations por Dave Methvin y jQuery 3.0: More interoperability, less Internet Explorer por Paul Krill.
Hay una nueva sintaxis en ECMA-262, 6ª Edición, Sección 14.2 llamada funciones de flecha que puede utilizarse para simplificar aún más los ejemplos anteriores. Utilizando la API de jQuery, en lugar de
promise.success(function (data) {
alert(data);
});
puedes escribir:
promise.success(data => alert(data));
o utilizando la API Promises/A+:
promise.then(data => alert(data));
Recuerda que siempre debes usar manejadores de rechazo ya sea con:
promise.then(data => alert(data), error => alert(error));
o con:
promise.then(data => alert(data)).catch(error => alert(error));
Consulta esta respuesta para ver por qué debes usar siempre los manejadores de rechazo con las promesas:
promise.then(alert)
porque sólo estás llamando a alert
con los mismos argumentos que tu callback, pero la sintaxis de la flecha es más general y te permite escribir cosas comopromise.then(data => alert("x is " + data.x));
Todavía no todos los navegadores soportan esta sintaxis, pero hay ciertos casos en los que estás seguro de en qué navegador se ejecutará tu código - por ejemplo, cuando escribes una extensión de Chrome, un complemento de Firefox, o una aplicación de escritorio usando Electron, NW.js o AppJS (ver esta respuesta para más detalles). Para el soporte de las funciones de flecha, ver:
await
palabra clave que en lugar de este código:functionReturningPromise()
.then(data => console.log('Data:', data))
.catch(error => console.log('Error:', error));
te permite escribir:
try {
let data = await functionReturningPromise();
console.log('Data:', data);
} catch (error) {
console.log('Error:', error);
}
Sólo se puede utilizar dentro de una función creada con la palabra clave async
. Para más información, consulte:
async
y await
se puede usar Babel:co
o coroutines de Bluebird:Algunas otras preguntas sobre promesas para más detalles:
La única manera de devolver los datos de la función sería hacer una llamada sincrónica en lugar de una asincrónica, pero eso congelaría el navegador mientras espera la respuesta.
Puedes pasar una función callback que maneje el resultado:
function testAjax(handleData) {
$.ajax({
url:"getvalue.php",
success:function(data) {
handleData(data);
}
});
}
Llámalo así:
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.
Ver el ejemplo de jquery docs: http://api.jquery.com/jQuery.ajax/ (aproximadamente 2/3 de la página)
Usted puede estar buscando el siguiente código:
$.ajax({
url: 'ajax/test.html',
success: function(data) {
$('.result').html(data);
alert('Load was performed.');
}
});
La misma página... más abajo.