¿Qué es una promesa en JavaScript? Todo lo que necesitas saber

Una de las preguntas más comunes entre los desarrolladores web que comienzan a usar JavaScript y a consumir APIs es: ¿Qué es una promesa en JavaScript? En este artículo, exploraremos en detalle las promesas, cómo funcionan y cómo puedes utilizarlas para manejar operaciones asíncronas en tu código. ¿Qué es una promesa en JavaScript? Una promesa […]

qué es una promesa en javascript

Una de las preguntas más comunes entre los desarrolladores web que comienzan a usar JavaScript y a consumir APIs es: ¿Qué es una promesa en JavaScript? En este artículo, exploraremos en detalle las promesas, cómo funcionan y cómo puedes utilizarlas para manejar operaciones asíncronas en tu código.

¿Qué es una promesa en JavaScript?

Una promesa (promise) es un objeto que representa la terminación o el fracaso de una operación que va a tardar un tiempo desconocido en obtener la respuesta de esa operación.

Una promise puede tener estos estados (PromiseState):

  • pending (pendiente): estado inicial, aún no se ha resuelto, ni tampoco ha fallado.
  • fulfilled (cumplida): lo que significa que la operación se ha resuelto con éxito.
  • rejected (rechazada): lo que significa que la operación ha fallado.

Las promesas nos ayudan a gestionar acciones asíncronas como peticiones a otros sitios fuera de nuestro entorno de ejecución en los cuales desconocemos el tiempo que va a tardar en ejecutarse y devolvernos esa información que hemos solicitado.

Esto las hace diferentes a las variables o a las funciones, ya que una promesa devuelve inmediatamente su respuesta, pero la devuelve como si fuera un “pagaré”, y de hecho te promete que te volverá lo que le has pedido o, fallará. De hecho, si falla, lo normal es rechazar el resultado.

Así que literalmente, una “promesa” nos promete que nos devolverá los datos que hemos solicitado.

¿Por qué usar promesas en JavaScript?

Cada vez que esperemos información que no estén directamente bajo nuestro control, deberíamos recibir una promesa. Las promesas van a evitar que la aplicación se bloquee cada vez que tengamos que esperar un resultado que vaya a tardar un tiempo desconocido, la devolución de unos datos pedidos a una API, eventos, acciones de usuario, etc.

Un caso real podrías ser la petición de datos a una API, esta, a su vez depende de un servidor o una base datos y puede tarde un tiempo desconocido en responder, así que sin una promesa, al ejecutarse la petición nuestra aplicación se quedaría esperando la respuesta hasta recibirla el tiempo que fuera (en el mejor de los casos de que la recibamos y no sea esta un error.)

Otro caso podría ser, pedir acceso al usuario desde el navegador a su micrófono o webcam, no tenemos ni idea del tiempo que pueda tardar el usuario o si va a denegar esta petición, pero la página o aplicación debe seguir funcionando.

Cómo obtener una promesa

Una de las maneras más comunes de obtener una promesa es mediante el uso de fetch(), que se ha convertido en un estándar y está integrado dentro de JavaScript. Pero existen también la librería de axios() cuyo funcionamiento es similar, pero necesitamos instalar el paquete.

Si ejecutamos estas líneas (mejor si lo hacemos desde un archivo HTML y lo ejecutamos en el navegador):

const apiURL = "https://jsonplaceholder.typicode.com/todos/1";
console.log(fetch(apiURL));

Obtendremos lo siguiente:

Lo que hemos hecho, ha sido pasarle el enlace de una API y hacer fetch a dicho enlace, y la respuesta ha sido la promesa.

Al hacer fetch, no sabe cuánto tiempo le costará, entonces con la promise te avisa y te dice algo así como “voy a buscarlo”, una vez traiga lo prometido, entonces (then) puedes coger esos datos y hacer lo que quieras con ellos.

Ejemplos de Promesas en JavaScript: Cómo Crear tus propios Promise

Para consumirlas, usaremos .then, async/await, pero ¿cómo creamos una promesa?, hay varias maneras:

new Promise

Crearemos una instancia del objeto Promise y le pasaremos como callback (resolve, reject) donde:

  • resolve: Devuelve un nuevo objeto Promise que se resuelve con el valor dado: resolve(valor)
  • reject: Devuelve un nuevo objeto Promise que se rechaza por el motivo indicado: reject(motivo).
const miPromesa = new Promise((resolve, reject) => {
          const exito = true; 
          // const existo = false;

          if (exito) {
            resolve("¡Éxito!");
          } else {
            reject("Ups.. hubo un error.");
          }
        });
      }

Promise.withResolvers()

Esto devuelve la promesa, pero además reject y resolve por separado.

Ejemplo:

ejemplo en la consola del navegador

Puede ser útil si queremospasar los métodos resolve y reject a otras partes de tu aplicación en lugar de hacer el trabajo dentro de la propia promesa.

Async

escribendo delante de una función “async”, esto cambiará la función y pasará de devolver una función convencional a devolver una promesa. Lo bueno de estas es que devolveremos un valor o una promesa, no tenemos que utilizar el método resolve, simplemente “return”.

Pruebalo en la consola:

async function fetchData() { return "Datos recibidos"; }
console.log(fetchData())
console.log( await fetchData())

¿Cómo se manejan las promesas en JavaScript?

Ahora que ya sabemos qué es una promesa y cómo crearlas, vamos a resolverlas

.then, .catch, .finally

La función que nos va a devolver una promesa la concatenamos con un .then, y a este then le pasamos como callback una función que será la que tenga la respuesta (típicamente se la llama response). Partiendo de uno de los ejemplos anteriores:

const apiURL = "https://jsonplaceholder.typicode.com/todos/1";
const data = fetch(apiURL).then(response => {
	return response.json();
});

Console.log(data);

Si la respuesta es rechazada, entonces será un .catch el que trate la respuesta, donde, el error estará disponible en la función callback.

const apiURL = "https://jsonplaceholder.typicode.com/todos/1";
const data = fetch(apiURL).then(response => {
	return response.json();
}) .catch(error => {
    console.error('Ha habido un error al recibir la respuesta:', error);
  });

Console.log(data);

Se puede añdir un .then siempre que devuelve una promesa, de  manera que se pueden concatenar varios y en el último añadir el catch().

Existe también un tercero que no es tan usado: .finally, el cual se ejecutará tanto si es resuelta como si es rechazada. Así que si nos da por duplicar código dentro del then y el catch, como cambiar un estado a false, o borrar un flag de loading, sin importar el resultado de la promesa, puede escribir eso dentro de .finaly.  

const apiURL = "https://jsonplaceholder.typicode.com/todos/1";
fetch(apiURL)
  .then(response => {
    console.log(data);
  })
  .catch(error => {
    console.error('Ha habido un error:', error);
  })
  .finally(() => {
    console.log('Esta acción se ejecutara siempre');
    // Aquí podrías poner cualquier código que necesites ejecutar independientemente de si hay error o no.
  });

Async / await para mejor legibilidad

Cuando se marca una función con async, se permite pausar la ejecución de esa función y continuarla una vez que la promesa se haya resuelto. Esto se hace utilizando la palabra clave await.

const createUser = async () => {
	return ‘David’;
}
const user = await createUser();
console.log(user)

La función marcada con async devuelve una promesa, que await resuelve.

En mi opinión, esta es una opción que hace el código más comprensible y ordenado. Aunque a veces encadenar múltiples .then() puede resultar en un código más conciso, la elección entre async/await y .then() realmente depende de las preferencias personales y del contexto en el que se esté trabajando.

.then vs async await

Uno de los problemas de usar el método then es que añaden otra capa de complejidad. Si necesitas acceder a los datos fuera de la promesa, debes crear una variable, pasarla y gestionar los valores por defecto antes y después de que la promesa devuelva su resultado.

await, por otro lado, ofrece una lectura más natural del código, se lee de una manera más intuitiva. Además, podemos esperar el valor, y una vez que lo tengamos, podemos hacer algo con él inmediatamente. No necesitamos preocuparnos tanto por la estructura del código como con then.

Conclusión

En resumen, entender qué es una promesa en JavaScript y cómo utilizarla es fundamental para manejar operaciones asíncronas de manera efectiva. Con las promesas, puedes asegurarte de que tu código sea más limpio y manejable.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Índice