Angular: Promesas Vs. Observables - Elige tu destino

La cuestión de si usar una Promesa o un Observable es válida. Déjame mostrarte una pequeña pista para decidir cuándo usar qué.

· 4 min de lectura
Angular: Promesas Vs. Observables - Elige tu destino


Cuando se trata de Angular, hay dos tipos principales de gestión de datos: el uso de Observables o Promises, siendo ambos capaces de gestionar código asíncrono en JavaScript. A primera vista, los Observables se ven como una alternativa más avanzada a las Promesas.

Pero, de hecho, son bastante diferentes. Desde tener APIs separadas, pasando por tener motivos diferentes, hasta ofrecer formas distintas de manejar el modelo asíncrono en JavaScript, Angular Observables y Angular Promises tienen sus propios poderes.

¿Cómo saber cuál es el adecuado para tu proyecto Angular? Vamos a discutirlos en detalle, comparar cada implementación, y ver las funciones, las ventajas y desventajas.

Dato curioso: Las promesas son un compromiso de valor a lo largo del tiempo; prometen esto. 😂

¿Qué son las promesas?

Hubo una época en JavaScript antes de las promesas. Era una época oscura. Todos los desarrolladores tenían miedo de acabar en el infierno: el infierno de las devoluciones de llamada.

Una devolución de llamada es una función llamada por una función para continuar cuando algo (tal vez asíncrono) se completa (por favor, tenga en cuenta que ya estoy usando funciones de flecha gorda aquí, que es una característica del lenguaje introducida mucho más tarde):

someMethod(input, output => {
  nextMethod(output, more => {
    hopefullyFinalMethod(more, realval => {
        dangThereIsMoreMethod(realval, () => alert('Now we are done!'));
    });
  });
});

Este es sólo un pequeño ejemplo hay otros mucho más profundos en la naturaleza. Por supuesto, puedes definir funciones para todas esas devoluciones de llamada y usarlas en lugar de la inline. Pero las cosas se complican cuando el contexto de llamada de la función necesita permanecer (por ejemplo, esto).

Reescribiendo el ejemplo anterior con Promesas, presuponiendo que los métodos son capaces de soportar esto, deberíamos obtener un código más ordenado:

someMethod(input)
.then(output => nextMethod(output))
.then(mode => hopefullyFinalMethod(more))
.then(realval => dangThereIsMoreMethod(realval))
.then(() => alert('Now we are done!'));

Como ves, esto es mucho más sencillo en cuanto a la indentación. Pero aún así, puedes notar que la legibilidad de las llamadas a métodos encadenados no es todavía cómo debería ser.

Cuando async/await estaba disponible, podías empezar a escribir código asíncrono como si fuera código síncrono usando las palabras clave apropiadas:

const output = await someMethod(input);
const more = await nextMethod(output);
const realval = await hopefullyFinalMethod(more);
await dangThereIsMoreMethod(realval);
alert('Now we are done!');

Este código debería ser la forma final mucho más legible y fácilmente comprensible ya que se ve el flujo de código inmediatamente. El uso de Observables aquí perjudicaría la legibilidad si no hay necesidad de ellos en absoluto.

Bonificación: En el caso de async/await, el manejo de errores es sólo un simple try/catch en su lugar:

try {
    const result = await asyncMethod();
} catch {
    alert('An error occured!');
}

¿Qué son los observables?


Hablando de Observables ¿qué son? En su forma más simple, puede ser como una Promesa. Proporciona un valor en el tiempo. Pero los Observables son mucho más que esto. Un Observable es capaz de entregar múltiples valores en el tiempo - es como el streaming. Puede ser cancelado o, en caso de errores, fácilmente reintentado. Numerosos Observables pueden combinarse, o puede haber una carrera para que sólo se utilice el primero. El marco RxJS para los Observables es poderoso.

Además, los Observables necesitan tener una suscripción para empezar a emitir valores. De lo contrario, no son más que un plano de código que maneja futuras emisiones. Si creas tu propio "productor" de valores, puedes reaccionar al suscribirte y desuscribirte. A continuación, puede iniciar, detener o derribar la emisión de valores.

Crear tu productor de un Observable es tan sencillo como instanciar una nueva instancia del mismo:

const observable = new Observable(subscriber => {
    // ...
    // put your value-producing logic here
    // ...
    return () => {
        // ...
        // put your teardown logic here
        // ...
    };
});

La instancia "subscriber" dada tiene el método next(value) para proporcionar valores. En caso de error, se debe llamar al método error(error). Y, cuando no hay más valores, se debe utilizar finalmente el método complete().

Cuando las promesas pueden ser la mejor opción


Una regla de oro podría ser que en todos los casos en los que quieras un solo valor en el tiempo, por ejemplo, de una petición HTTP, deberías usar una Promesa. Normalmente, esto no debería ser un problema si aceptas los siguientes inconvenientes:

  • No puedes cancelar fácilmente una promesa.
  • No se puede repetir o reintentar fácilmente una promesa.

¿Por qué estos inconvenientes pueden ser un problema para ti?

Supongamos que estás desarrollando una aplicación Angular. Normalmente solicitas algunos datos cuando el usuario navega hacia tu componente. Cuando esto lleva un tiempo, y el usuario navega lejos, la petición HTTP continúa y se completa descargando todos los datos "inútiles". Por supuesto, esto podría ser archivado de alguna manera mediante la implementación de alguna lógica compleja o utilizar un marco ya construido para esto.

Por otro lado, para repetir o reintentar una Promesa, también se necesita alguna lógica aún más compleja para lograrlo (o utilizar una librería, si está disponible).

Pero a veces, incluso cuando sólo hay un valor disponible, la construcción de un pipe Observable podría ser la mejor opción si el código sería mucho más complejo sin ella.

Inconvenientes:

  • Tienes que aprender un framework complejo.
  • Podrías tender a usar Observables en todas partes.
  • Como se mencionó anteriormente, el framework RxJS es complejo. Hay muchos operadores y posibilidades de trabajar con ese estilo de programación reactiva.

Conclusión


Un gran poder conlleva también una gran responsabilidad. Lo mejor sería no utilizar los Observables como respuesta a cualquier problema que surja. El código puede parecer mucho más difícil de entender cuando los pipes de los Observables se vuelven significativas, o la forma reactiva es innecesaria en este punto particular del código.

Fuente

Plataforma de cursos gratis sobre programación