El objeto Promise
(Promesa) es usado para computaciones asíncronas. Una promesa representa un valor que puede estar disponible ahora, en el futuro, o nunca.
Sintaxis
new Promise( /* ejecutor */ function(resolver, rechazar) { ... } );
Parámetros
- ejecutor
- Una función con los argumentos
resolver
yrechazar
. La funciónejecutor
es ejecutada inmediatamente por la implementación de la Promesa, pasándole las funcionesresolver
yrechazar
(el ejecutor es llamado incluso antes de que el constructor de laPromesa
devuelva el objeto creado). Las funcionesresolver
yrechazar
, al ser llamadas, resuelven o rechazan la promesa, respectivamente. Normalmente el ejecutor inicia un trabajo asíncrono, y luego, una vez que es completado, llama a la funciónresolver
para resolver la promesa o la rechaza si ha ocurrido un error.
Si un error es lanzado en la función ejecutor, la promesa es rechazada y el valor de retorno del ejecutor es rechazado.
Descripción
Una Promesa es un proxy para un valor no necesariamente conocido en el momento que es creada la promesa. Permite asociar manejadores que actuarán asincrónicamente sobre un eventual valor en caso de éxito, o la razón de falla en caso de una falla. Esto permite que métodos asíncronos devuelvan valores como si fueran síncronos: en vez de inmediatamente retornar el valor final, el método asíncrono devuelve una promesa de suministrar el valor en algún momento en el futuro.
Una Promesa
se encuentra en uno de los siguientes estados:
- pendiente (pending): estado inicial, no cumplida o rechazada.
- cumplida (fulfilled): significa que la operación se completó satisfactoriamente.
- rechazada (rejected): significa que la operación falló.
Una promesa pendiente puede ser cumplida con un valor, o rechazada con una razón (error). Cuando cualquiera de estas dos opciones sucede, los métodos asociados, encolados por el método then de la promesa, son llamados. (Si la promesa ya ha sido cumplida o rechazada en el momento que es anexado su correspondiente manejador, el manejador será llamado, de tal manera que no exista una condición de carrera entre la operación asíncrona siendo completada y los manejadores siendo anexados)
Como los métodos
y Promise.prototype.then()
retornan promesas, éstas pueden ser encadenadas.Promise.prototype.catch()
No confundir con: Varios lenguajes tienen mecanismos para evaluar perezosamente y postergar una computación, a los que también les llaman "promesas" - p.ej.: Scheme. Las promesas en JavaScript representan procesos que ya están sucediendo, y pueden ser encadenados con funciones callback. Si lo que se busca es evaluar perezosamente una expresión, se debe considerar la función flecha (arrow function) sin argumentos: f = () => expresión
para crear la expresión evaluada perezosamente, y f()
para evaluar.
Nota: Una promesa se dice que está determinada (settled) si se ha cumplido o si se ha rechazado, pero no está pendiente. Con promesas también se usa el término resuelta — esto significa que la promesa está determinada, o que se encuentra bloqueada dentro de una cadena de promesas. States and fates de Domenic Denicola contiene mas detalles sobre la terminología de las promesas.
Propiedades
Promise.length
- Propiedad longitud cuyo valor es siempre 1 (numero de argumentos del constructor).
Promise.prototype
- Representa el prototipo del constructor
Promise
.
Métodos
Promise.all(iterable)
- Devuelve una de dos promesas: una que se cumple cuando todas las promesas en el argumento iterable han sido cumplidas, o una que se rechaza tan pronto como una de las promesas del argumento iterable es rechazada. Si la promesa retornada es cumplida, lo hace con un arreglo de los valores de las promesas cumplidas en el mismo orden definido en el iterable. Si la promesa retornada es rechazada, es rechazada con la razón de la primera promesa rechazada en el iterable. Este método puede ser útil para agregar resultados de múltiples promesas
Promise.race(iterable)
- Devuelve una promesa que se cumple o rechaza tan pronto como una de las promesas del iterable se cumple o rechaza, con el valor o razón de esa promesa.
Promise.reject(reason)
- Devuelve un objeto
Promise
que es rechazado con la razón dada.
Promise.resolve(value)
- Devuelve un objeto
Promise
que es resuelto con el valor dado. Si el valor es un thenable (p.ej. tiene un métodothen
), la promesa devuelta "seguirá" este thenable, adoptando su eventual estado; de lo contrario la promesa devuelta será cumplida con el valor. Generalmente, si se quiere saber si un valor es una promesa o no, se podría usar -Promise.resolve(value)
y trabajar con el valor devuelto como una promesa.
Prototipo Promise
Propiedades
Métodos
Ejemplos
Súper simple (¡10 líneas!)
let miPrimeraPromise = new Promise((resolve, reject) => {
// Llamamos a resolve(...) cuando lo que estabamos haciendo finaliza con éxito, y reject(...) cuando falla.
// En este ejemplo, usamos setTimeout(...) para simular código asíncrono.
// En la vida real, probablemente uses algo como XHR o una API HTML5.
setTimeout(function(){
resolve("¡Éxito!"); // ¡Todo salió bien!
}, 250);
});
miPrimeraPromise.then((successMessage) => {
// succesMessage es lo que sea que pasamos en la función resolve(...) de arriba.
// No tiene por qué ser un string, pero si solo es un mensaje de éxito, probablemente lo sea.
console.log("¡Sí! " + successMessage);
});
Creando una Promise
Este pequeño ejemplo muestra el mecanismo de una Promise
. El método testPromise()
se llama cada vez que se pulsa el <button>
. Esto crea una promesa que se cumplirá, aplicando window.setTimeout()
, al contador de la promesa (partiendo desde 1) aleatoriamente cada 1-3 segundos. El constructor de la Promise() es usado para crear dicha promesa.
El cumplimiento de la promesa simplemente se registra, a través de una llamada de retorno al cumplirse utilizando p1.then()
. A los pocos registros muestra cómo la parte síncrona del método se desacopla de la finalización asíncrona de la promesa.
'use strict';
var promiseCount = 0;
function testPromise() {
var thisPromiseCount = ++promiseCount;
var log = document.getElementById('log');
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Comenzó (<small>Comenzó el código sincrónico</small>)<br/>');
// Hacemos una promesa: prometemos un contador numérico de esta promesa,
// empezando por 1 (después de esperar 3s)
var p1 = new Promise(
// La función resolvedora es llamada con la
// habilidad de resolver o rechazar la promesa
function(resolve, reject) {
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Comenzó la promesa (<small>Código asíncrono comenzó</small>)<br/>');
// Esto es solo un ejemplo para crear asincronismo
window.setTimeout(
function() {
// ¡Cumplimos la promesa!
resolve(thisPromiseCount);
}, Math.random() * 2000 + 1000);
}
);
// Definimos qué hacer cuando la promesa es resuelta/cumplida con la llamada
// al método then(). La llamada al método catch() define qué hacer si
// la promesa es rechazada
p1.then(
// Registrar el valor de la promesa cumplida
function(val) {
log.insertAdjacentHTML('beforeend', val +
') Promesa cumplida (<small>Código asíncrono terminado.</small>)<br/>');
})
.catch(
// Registrar la razón del rechazo
function(reason) {
console.log('Manejar promesa rechazada ('+reason+') aquí.');
});
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Promesa hecha (<small>Código síncrono terminado. </small>)<br/>');
}
Este ejemplo es ejecutado cuando pulsas el botón. Necesitas un navegador que soporte Promise
. Al pulsar el botón varias veces en un período corto de tiempo, verás las diferentes promesas siendo cumplidas una tras otra.
Cargando una imagen con XHR
Otro ejemplo sencillo utilizando Promise
y XMLHttpRequest
para cargar una imagen está disponible en el repositorio js-examples de MDN en GitHub. También puedes verlo en acción. Cada paso está comentado y te permite seguir de cerca la arquitectura detrás de las Promesas y XHR.
Especificaciones
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) La definición de 'Promise' en esta especificación. |
Standard | Initial definition in an ECMA standard. |
ECMAScript (ECMA-262) La definición de 'Promise' en esta especificación. |
Living Standard |
Compatibilidad de navegadores
To contribute to this compatibility data, please write a pull request against this file: https://github.com/mdn/browser-compat-data/blob/master/javascript/promise.json.
No compatibility data found. Please contribute data for "javascript/promise" (depth: 1) to the MDN compatibility data repository.
Ver también
- Promises/A+ specification
- Venkatraman.R - JS Promise (Part 1, Basics)
- Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)
- Jake Archibald: JavaScript Promises: There and Back Again
- Domenic Denicola: Callbacks, Promises, and Coroutines – Asynchronous Programming Patterns in JavaScript
- Matt Greer: JavaScript Promises ... In Wicked Detail
- Forbes Lindesay: promisejs.org
- Nolan Lawson: We have a problem with promises — Common mistakes with promises
- Promise polyfill
- Udacity: JavaScript Promises