2. Una promesa es un objeto que representa un
posible valor en el futuro. Se utiliza cuando se
necesita operar con un resultado del que aún no
se conoce su valor, algo muy típico en
programación asíncrona.
¿Qué es una Promesa?
3. Una promesa puede tener 3 estados posibles:
● pendiente: el resultado aún no se conoce.
● satisfecho: cuando el resultado es correcto.
● rechazado: cuando el resultado es incorrecto.
¿Qué es una Promesa?
4. El estado inicial de una promesa es pendiente.
Una vez que el resultado es conocido, en función
de este resultado, el estado de la promesa pasa
a ser satisfecho o rechazado, y este estado ya no
puede volver a cambiar.
¿Qué es una Promesa?
5. ¿Qué es una Promesa?
pendiente
satisfecho
rechazado
resultado
conocido
6. Las promesas (también llamadas “futuros”) se
usan para trabajar con código asíncrono, algo
muy típico en JavaScript.
De hecho se pueden encontrar en varios
lenguajes de programación: JavaScript, Python,
Java, Ruby, …
¿Cuándo se deben usar?
7. Gracias a las promesas, en JavaScript podemos
pasar de un código profundamente anidado y
difícil de entender como este...
asyncFunction1(function(error, result) {
asyncFunction2(function(error, result) {
asyncFunction3(function(error, result) {
asyncFunction4(function(error, result) {
// ...
});
});
});
});
¿Cuándo se deben usar?
8. … a un código mucho más legible y simple como este:
¿Cuándo se deben usar?
asyncFunction1()
.then(asyncFunction2)
.then(asyncFunction3)
.then(asyncFunction4)
.catch(handleError);
9. En JavaScript las promesas se crean con el
constructor Promise. Este constructor recibe como
único argumento una función, que a su vez contiene
dos parámetros: resolve y reject.
¿Cómo se usan?
var promise = new Promise(function(resolve, reject) {
// …
});
10. Los parámetros resolve y reject son funciones para
cambiar el estado de la promesa, que inicialmente es
pendiente (pending). Con resolve el estado de la promesa
pasa a ser satisfecho (fulfilled). Y con reject el estado
cambia a rechazado (rejected).
¿Cómo se usan?
pendiente
satisfecho
rechazado
resultado
conocido
resolve(value)
reject(reason)
11. ¿Cómo se usan?
var promise = new Promise(function(resolve, reject) {
// …
if (condition) {
resolve(value);
} else {
reject(reason);
}
});
La función resolve() recibe como argumento el resultado
de la operación cuando ésta se ha realizado
correctamente. Por contra, para indicar que hubo algún
problema se usa la función reject(), pasándole como
argumento un mensaje (string) o una instancia de Error.
12. La ventaja principal de las promesas es que se
pueden encadenar mediante el método then(), ya que
este método devuelve a su vez otra promesa. De esta
manera, un código asíncrono implementado con
promesas tendría un aspecto similar a este:
¿Cómo se usan?
asyncFunction1()
.then(asyncFunction2)
.then(asyncFunction3)
.then(asyncFunction4);
13. El método then() contiene dos parámetros
opcionales: onFulfilled y onRejected. Ambos
son funciones.
El método then()
14. El primer parámetro, onFulfilled, recibe
automáticamente el resultado devuelto por la
promesa anterior cuando el estado de ésta cambia de
pendiente (pending) a satisfecho (fulfilled).
El método then()
promise.then(function(value) {
// …
});
15. El segundo parámetro, onRejected, recibe
automáticamente la razón (mensaje o instancia de
Error) devuelta por la promesa anterior cuando el
estado de ésta cambia de pendiente (pending) a
rechazado (rejected).
El método then()
promise.then(..., function(reason) {
// …
});
16. Para pasar en then() únicamente la función
onRejected es necesario pasar undefined como
primer parámetro. Y esto es precisamente lo que
hace internamente el método catch(). Este método
equivale a un then() que sólo sirve para capturar
errores.
El método catch()
promise.catch(function(reason) {
// …
});
17. Tanto then() como catch() devuelven una nueva
promesa. El estado y valor de ésta depende del
resultado devuelto por onFulfilled y onRejected.
then/catch
var promise2 = promise1.then(function(value1) {
// …
});
18. Las funciones onFulfilled y onRejected pueden
devolver:
● Una promesa
● Un valor
● Una excepción
then/catch
19. Si onFulfilled o onRejected devuelve una promesa,
entonces la promesa devuelta por then() adquiere el
mismo estado y valor de dicha promesa.
onFulfilled/onRejected
var promise2 = promise1.then(function(value1) {
// …
return new Promise(function(resolve, reject) {
// …
});
});
20. Si onFulfilled o onRejected devuelve un valor x,
entonces la promesa devuelta por then() pasa al
estado satisfecho (fulfilled) tomando como valor el
valor x.
onFulfilled/onRejected
var promise2 = promise1.then(function(value1) {
// …
return valor2;
});
21. Si en onFulfilled o en onRejected se produce una
excepción ex, entonces la promesa devuelta por
then() pasa al estado rechazado (rejected) tomando
como razón el objeto ex.
onFulfilled/onRejected
var promise2 = promise1.then(function(value1) {
// …
throw new Error(“¡error!”);
});
22. A pesar de que las promesas se han incluido
recientemente en la última versión de JavaScript
(ES6), a día de hoy ya está soportado por la mayoría
de navegadores modernos, excepto Internet Explorer.
Soporte
23. De todas formas existen multitud de bibliotecas
JavaScript compatibles con la especificación de las
promesas implementada en ES6, por lo que en
principio se podrían usar en cualquier navegador. Por
ejemplo, con este polyfill.
Soporte
24. jQuery es la excepción, ya que la implementación de
las promesas incluida en jQuery no cumple la
especificación de las promesas, y difiere en gran
medida de la versión estándar que hemos visto hasta
ahora.
jQuery
25. El problema de no implementar la versión estándar es
que pueden surgir problemas al conectar (mediante
el método then()) las “promesas” de jQuery con
promesas estándar.
jQuery
26. jQuery implementa su propia versión de las promesas
mediante el objeto constructor Deferred. Este objeto
proporciona una larga de lista de métodos útiles para
realizar tareas asíncronas. Entre ellos su propia
versión de then() (con tres parámetros y un
comportamiento diferente que el estándar).
jQuery
27. Una de las mayores diferencias entre las “promesas”
de jQuery y las promesas estándar es el tratamiento
de las excepciones dentro del método then().
jQuery then()
28. En las promesas estándar las excepciones se
capturan sólo dentro del método then()/catch(),
concretamente con la función onRejected(), pasada
como 2º parámetro a then(). Es decir, las
excepciones son silenciosas y no cortan el flujo de
ejecución de las promesas.
jQuery then()
29. Promesas estándar
var promise2 = promise1.then(function(value1) {
// …
throw new Error(“¡error!”); // excepción silenciosa
});
// El código sigue ejecutándose
promise2.catch(function(err) {
console.log(err); // => ¡error!
});
30. En las “promesas” de jQuery las excepciones no son
silenciosas y tienen el comportamiento habitual:
interrumpir la ejecución.
jQuery then()
31. jQuery then()
var $promise2 = $promise1.then(function(value1) {
// …
throw new Error(“¡error!”); // interrupción
});
// A partir de aquí el código no se ejecutará
$promise2.fail(function(err) {
console.log(err);
});
32. La única manera segura de conectar las “promesas”
de jQuery con las promesas estándar es creando una
promesa estándar a partir de una “promesa” de
jQuery usando el método Promise.resolve():
jQuery
var $promise = $.get(‘https://api.github.com’);
var promise = Promise.resolve($promise);