Artículo original escrito por Kingsley Ubah
Artículo original What is a Promise? JavaScript Promises for Beginners
Traducido y adaptado por Julio Vargas

Si eres un principiante en JavaScript, puede que estés luchando para entender lo que realmente es una promesa.

Recientemente publiqué esto como un hilo en Twitter y se llenó de respuestas. Entonces decidí expandirlo a este tutorial introductorio de promesas de JavaScript.

He leído un montón de artículos sobre promesas y el problema es que muchas de estas guías no las explican de una forma entendible. La gente no entiende lo que es una promesa en JavaScript porque realmente no saben de qué se trata y como se comporta de una manera simple y en términos entendibles.

Entonces, en este artículo, te estaré contando una historia que explica que son exactamente las promesas y como funcionan exactamente. También te voy a mostrar como usarlas en JavaScript con algunos ejemplos.

¿Qué es una promesa en JavaScript?

Imagina que estás entrevistando gente que busca empleo en tu compañía.

Un hombre joven entra frenéticamente a la entrevista, cuando su turno está a punto de llegar, se da cuenta de que olvidó su currículo.

Sería un fastidio ¿verdad?

Sin embargo, no está intimidado. Por suerte, para él, tiene un compañero que aún está en casa en ese momento.

Lo llama rápidamente y le pide ayuda, le suplica que le ayude a encontrar su currículo. Su compañero le PROMETE enviar un mensaje de texto tan pronto tenga algo para reportar.

Asumiendo que el currículo es encontrado eventualmente, podría escribirle:

“!Listo, encontré tu currículo¡”

Pero si no la encuentra, se supone que mandará un mensaje de texto reportando la razón por la que no pudo encontrar su currículo. Por ejemplo, podría enviar el siguiente mensaje para su amigo que está siendo entrevistado

“Lo siento, no pude encontrar tu currículo porque no encontré la llave de tu caja fuerte.”

Mientras tanto, la entrevista continúa según lo planeado y el entrevistador se aferra a la promesa de encontrar el currículum, no en el currículum. En ese momento, el entrevistador pone el currículo como PENDIENTE por entregar.

El entrevistado responde todas las preguntas que le hacen. Aunque en última instancia, su empleo sigue dependiendo en el ESTADO FINAL de su currículo.

Finalmente su compañero le escribe. Como lo habíamos discutido antes, Si él no encuentra el currículo, te lo dirá junto como la razón de porque no lo encontró.

Si eso sucede, la entrevista podría terminar y el entrevistado sería.

Por otro lado, si su compañero encuentra el currículo, le diría muy felizmente que cumplió con su cometido y que puede seguir adelante y CUMPLIR sus esperanzas de conseguir el trabajo.

¿Entonces como se traslada esto a JavaScript?

El compañero prometiendo encontrar el currículo y escribirle, es sinónimo de como definimos una promesa en JavaScript. El código no devuelve directa o inmediatamente un valor, en vez de eso devuelve una promesa de que eventualmente nos retornará el valor posteriormente.

Una promesa es asincrónica, lo que significa que necesita tiempo para resolverse o finalizar. Justamente como la búsqueda del currículo tomó tiempo.

Por esa razón, el entrevistador decide no perder el tiempo, entonces comienza a entrevistar el candidato basado en su promesa de que su currículo llegará. Estamos utilizando la promesa de traer un currículum en lugar del currículum.

El motor de JavaScript tampoco pierde el tiempo, él comienza a ejecutar otras partes del código, a la espera del valor devuelto de la promesa.

El mensaje de texto contiene el estado de la búsqueda del currículum. Con una promesa de JavaScript, esto también es llamado “valor devuelto”.

Si el mensaje es de “éxito”, procederíamos a contratar el candidato y a concederle el puesto. Si falla, rechazamos su candidatura.

Con las promesas de JavaScript hacemos esto usando una función callback (gestores de promesas). Estas funciones están definidas en el método anidadothen().

Para especificar que callbacks usar, usa las siguientes funciones:

  • resolve(value): Esta indica que la tarea asincrónica se realizó correctamente. Esto ejecutará el callback de cumplimiento en el controlador then().
  • reject(error): Esta indica un error mientras se intenta realizar la tarea asincrónica. Esta ejecutará el callback de error en el controlador  then().

Si la promesa se cumple, el callback de cumplimiento se ejecutará, de lo contrario se ejecuta el callback de error.

Una promesa es un simple texto provisional para una tarea asincrónica que aún no se ha completado. Cuando defines una promesa en tu script, en vez de devolver un valor inmediatamente, esta devuelve una promesa.

Como escribir una promesa en JavaScript.

Puedes definir una promesa en JavaScript llamando a la clase Promise y construyendo un objeto, así:

const miPromesa = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('este es el valor que eventualmente devolverá la promesa');
  }, 300);
});

console.log(miPromesa);
Ejemplo uno

Ejecutar esto en la consola, devolverá un objeto Promise:

promise-console-1

Aunque, crear un objeto no es la única forma de definir una promesa. También puedes usar la API incorporada Promise para lograr lo mismo:

const otraPromesa = Promise.resolve("este es el valor que eventualmente devolverá la promesa")

console.log(otraPromesa);
Ejemeplo dos

Mientras que la promesa en el primer ejemplo esperará 3 segundos antes de cumplir la promesa con el mensaje  este es el mensaje que eventual..., la promesa en el segundo ejemplo cumplirá inmediatamente y con el mismo mensaje.

Promesas rechazadas en JavaScript.

Una promesa también puede ser rechazada. La mayoría del tiempo, se rechazan porque JS encuentra algún tipo de error mientras ejecuta el código asincrónico. En ese escenario, llama la función reject().

Mira un ejemplo simple e inventado de como una promesa puede ser rechazada:

const miPromesa = new Promise((resolve, reject) => {
  let a = false;
  setTimeout(() => {
    return (a) ? resolve('se encontró a'): reject('lo siento, no se encontró a');
  }, 300);
}); 




Ejemplo tres

¿Puedes encontrar la razón por la cual esta promesa es rechazada? Si dijiste “porque a no es falso” !Felicitaciones¡

La promesa en el tercer ejemplo se resolverá con un rechazo, después de un tiempo de espera de 3 segundos, porque la declaración (a)? se resuelve en falso, lo que desencadenará reject.

Como encadenar promesas con then()

Cuando finalmente la promesa devuelva un valor, normalmente querrás hacer algo con ese valor devuelto.

Por ejemplo, si estabas haciendo una solicitud de red, podrías querer acceder a ese valor y mostrarlo en la página para el usuario.

Puedes definir las dos funciones callback que quieres llamar cuando una promesa se cumple o se rechaza. Estas funciones se definen dentro de un método then() anidado:

const otraPromesa = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('este es el valor eventual que devolverá la promesa');
  }, 300);
});

// CONTINUACIÓN
otraPromesa
.then(value => { console.log(value) }) 
Ejemplo cuatro

Ejecutar el código anterior, mostrará el mensaje de cumplimiento en la consola, después de tres segundos:

EVENTAL-RETURN
'este es el valor eventual que devolverá la promesa'

Ten en cuenta que puedes anidar tantas promesas como quieras. Cada paso se ejecutará después del paso anterior, tomando el valor devuelto de ese paso anterior:

const otraPromesa = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('este es el valor que eventualmente devolverá la promesa');
  }, 300);
});

otraPromesa
.then(fulfillFn, rejectFn)
.then(fulfilFn, rejectFn)
.then(value => { console.log(value) })
Ejemplo cinco

Pero se nos olvidó algo importante.

Mantén siempre en mente que el método then() debe tomar ambos valores, el manipulador de cumplimiento y el de rechazo. De esta forma, el primero es llamado si la promesa se cumple y el segundo si la promesa es rechazada con un error.

Las promesas en los ejemplos cuatro y cinco no incluyen un segundo controlador. Entonces, asumiendo que se encuentra un error, no habrá un manipulador de rechazo para dicho error.

Si solo vas a definir una función callback (también conocida como un manipulador de cumplimiento) en then(), después necesitarás anidar un método catch() en el final de la cadena de promesas para  detectar cualquier posible error.

Como usar el método catch() en JS.

El métodocatch()  siempre será llamado cuando quiera que se encuentre un error en cualquier punto a lo largo de la cadena de promesas:

const miPromesa = new Promise((resolve, reject) => {
  let a = false;
  setTimeout(() => {
    return (a) ? resolve('se encontró a'): reject('lo siento, no se encontró a');
  }, 300);
}); 

myPromise
.then(value => { console.log(value) })
.catch(err => { console.log(err) });


Ejemplo seis

Dado que  myPromise eventualmente se resolverá como un rechazo la función definida en el then() anidado será ignorado. En su lugar el manipulador se ejecutará catch()  lo que debería mostrar el siguiente mensaje de error en la consola:

Catch
"lo siento, no se encontró a"

Para terminar.

Las promesas de JavaScript son una poderosa característica que te ayudarán a ejecutar código asincrónico en JavaScript. En la mayoría, si no en todas las entrevistas para empleos que usen JS, tu entrevistador probablemente hará una pregunta sobre las promesas.

En este artículo, expliqué lo que es una promesa en términos simples, y mostré su uso práctico con algunos ejemplos en código.

Espero que hayas adquirido algo útil de este artículo. Si te gustan los tutoriales con respecto a la programación, deberías ver mi blog (en inglés), Regularmente publico artículos sobre desarrollo de software.

Gracias por leer y nos vemos pronto.

Posdata: Si estás aprendiendo JavaScript, he creado un eBook que te enseña 50 temas en JS con notas digitales dibujadas a mano Miralo aquí. (en inglés)