Dentro de las características especiales de JavaScript, hay algunas que son realmente curiosas, sobretodo por el nombre que tienen. Desde mi punto de vista, una de estas características son las promises, o promesas en castellano. :)

¿Qué es una Promise?

Una Promise en JavaScript es un objeto que representa la eventual finalización, o fallo de una operación asíncrona, y su valor resultante.

Una promise recibe una "función ejecutora" que acepta dos argumentos: resolve y reject

¿Cómo funciona?

La “función ejecutora” de Promise es llamada antes que el constructor de Promise retorne el objeto creado. El objetivo de resolve y reject es, como el nombre indica, resolver y rechazar la promise, respectivamente. Pensa que la idea es poder utilizar Promise en tareas asíncronas, y cuando esta tarea se finalice se llame a resolve si todo correcto, o a reject si ha habido algún error.

¿Para qué sirve una promise?

Funcionamiento de una Promise by Mozilla

Una Promise es un proxy para un valor que no conocemos en el momento en que creamos la promise. Su objetivo es el de asociar controladores con un eventual éxito o fallo de una tarea asíncrona. Esto permite que métodos asíncronos retornen valores como métodos síncronos, y no el valor final.

Estados de una Promise

Una Promise puede tener uno de los siguientes estados:

  1. Pending: estado inicial, ni cumplido (fulfilled), ni rechazado (rejected)
  2. Fulfilled: la operación se ha completado con éxito
  3. Rejected: La operación ha fallado

Es importante saber que si la promise es fulfilled o rejected, es también inmutable. Esto significa que ya no se podrá cambiar.

Ejemplo básico de Promise

Ejemplo básico de una Promise con setTimeout()

Cómo has podido ver en el ejemplo anterior, llamamos resolve() cuando lo que estábamos haciendo de forma asíncrona se completó satisfactoriamente, y usaríamos reject() si hubiera fallado.

En este ejemplo utilizamos setTimeout() para simular una tarea asíncrona. También has podido observar que en el método then() de nuestra Promise, “successMessage” es el valor de lo que pases en resolve(). En este caso le hemos pasado una cadena, pero podría haber sido también un objeto, ¡o una Promise!  

Buenas prácticas de Promise

Te dejo tres buenas prácticas para que las integres en tus procesos de desarrollo con Promises.

  1. Utiliza Promise.all(), Promise.spread() y otros métodos para controlar el flujo. Promise.all() es uno de los métodos de Promise que más utilizo, sobretodo cuando quiero acceder a vários objetos relacionados con el mismo usuario desde una API.
  2. Para limitar la concurrencia usa Promise.map(). El método map(), acepta una opción “concurrency” que te permite limitar el número de Promises creadas.
  3. Usa siempre un extra catch() para controlar los errores. Puede suceder que tengas la tentación de definir controladores de rechazo como el segundo argumento para llamadas al método then(). No es una buena práctica.

Conclusión

Si, por ejemplo, estás trabajando con funciones síncronas de JavaScript para leer ficheros, es natural que no quieras que tus funciones estén bloqueando otras operaciones - ya que JavaScript es un lenguaje de enfilamiento simple -, que tu aplicación tenga un  buen rendimiento y sea responsiva.

Pensar simplemente en una operación asíncrona no es suficiente, ya que te puedes encontrar problemas relacionados con "parámetros extras" que generan confusión de lectura - ¿cuál es el valor de entrada y cuál es el de salida?-, si funciona con flujos de control, y si es fácil gestionar posibles errores.

Las Promises quieren lidiar contigo en estos temas, ayudándote a gestionar los errores, o escribir código más limpio sin que cambies la arquitectura subyacente. Esto significa que puedes implementarlas en tu próximo proyecto de Vanilla JavaScript y usarlas en otras operaciones asíncronas de tu aplicación.

¿De qué formas usas Promises en tus aplicaciones?

Foto: moritz320 en Pixabay

Fuentes: