¿Cuál es la diferencia entre Promesas y Observables

angular promise rxjs angular-promise angular-observable


¿Cuál es la diferencia entre Promise y Observable en Angular?

Un ejemplo de cada uno de ellos sería útil para comprender ambos casos.¿En qué escenario podemos usar cada caso?




Answer 1 Günter Zöchbauer


Promise

Una Promise maneja un solo evento cuando una operación asincrónica se completa o falla.

Nota: Existen bibliotecas de Promise que admiten la cancelación, pero ES6 Promise no lo hace hasta ahora.

Observable

Un Observable es como un Stream (en muchos idiomas) y permite pasar cero o más eventos donde se llama la devolución de llamada para cada evento.

A menudo, Observable se prefiere a Promise porque proporciona las características de Promise y más. Con Observable no importa si desea manejar 0, 1 o múltiples eventos. Puede utilizar la misma API en cada caso.

Observable también tiene la ventaja sobre Promise de ser cancelable . Si el resultado de una solicitud HTTP a un servidor o alguna otra operación asíncrona costosa ya no es necesaria, la Subscription de un Observable permite cancelar la suscripción, mientras que una Promise eventualmente llamará a la devolución de llamada exitosa o fallida, incluso cuando no necesita la notificación o el resultado que proporciona más.

Observable proporciona operadores como map , forEach , reduce , ... similar a una matriz

También hay operadores poderosos como retry() o replay() , ... que a menudo son bastante útiles.




Answer 2 trungk18


Tanto Promises como Observables nos proporcionan abstracciones que nos ayudan a lidiar con la naturaleza asincrónica de nuestras aplicaciones. La diferencia entre ellos fue señalada claramente por @ Günter y @Relu.

Ya que un fragmento de código vale más que mil palabras,veamos el siguiente ejemplo para entenderlo más fácilmente.

Gracias @ Christoph Burgdorf por el increíble artículo


Angular utiliza Rx.js Observables en lugar de promesas para tratar con HTTP.

Supongamos que está construyendo un función de búsqueda que debería mostrarle resultados instantáneamente a medida que escribe. Suena familiar, pero hay muchos desafíos que vienen con esa tarea.

  • No queremos llegar al punto final del servidor cada vez que el usuario presiona una tecla, debería inundarlos con una tormenta de HTTP solicitudes HTTP . Básicamente, solo queremos presionarlo una vez que el usuario ha dejado de escribir en lugar de con cada pulsación de tecla.
  • No golpee el punto final de búsqueda con el mismos parámetros de consulta para solicitudes posteriores.
  • Manejar respuestas fuera de orden. Cuando tenemos varias solicitudes en vuelo al mismo tiempo, debemos tener en cuenta los casos en que vuelven en un orden inesperado. Imagine que primero escribimos computadora , paramos, se apaga una solicitud, escribimos auto , paramos, se apaga una solicitud. Ahora tenemos dos solicitudes en vuelo. Desafortunadamente, la solicitud que lleva los resultados para la computadora regresa después de la solicitud que lleva los resultados para automóvil .

La demostración consistirá simplemente en dos archivos: app.ts y wikipedia-service.ts . Sin embargo, en un escenario del mundo real, probablemente dividiríamos las cosas más arriba.


A continuación se muestra una implementación basada en Promise que no maneja ninguno de los casos límite descritos.

wikipedia-service.ts

import { Injectable } from '@angular/core';
import { URLSearchParams, Jsonp } from '@angular/http';

@Injectable()
export class WikipediaService {
  constructor(private jsonp: Jsonp) {}

  search (term: string) {
    var search = new URLSearchParams()
    search.set('action', 'opensearch');
    search.set('search', term);
    search.set('format', 'json');
    return this.jsonp
                .get('http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK', { search })
                .toPromise()
                .then((response) => response.json()[1]);
  }
}

Estamos inyectando el servicio Jsonp para realizar una solicitud GET contra la API de Wikipedia con un término de búsqueda determinado. Observe que llamamos a toPromise para pasar de un Observable<Response> a un Promise<Response> . Finalmente, termina con una Promise<Array<string>> como el tipo de retorno de nuestro método de búsqueda.

app.ts

// check the plnkr for the full list of imports
import {...} from '...';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Wikipedia Search</h2>
      <input #term type="text" (keyup)="search(term.value)">
      <ul>
        <li *ngFor="let item of items">{{item}}</li>
      </ul>
    </div>
  `
})
export class AppComponent {
  items: Array<string>;

  constructor(private wikipediaService: WikipediaService) {}

  search(term) {
    this.wikipediaService.search(term)
                         .then(items => this.items = items);
  }
}

No es una gran sorpresa aquí tampoco. Inyectamos nuestro Servicio WikipediaService y exponemos su funcionalidad a través de un método de búsqueda a la plantilla. La plantilla simplemente se une al keyup y llama a la search(term.value) .

Desenvolvemos el resultado de la Promesa de que el método de búsqueda del Servicio Wikipedia regresa y lo exponemos como una simple Matriz de cadenas a la plantilla para que podamos tener *ngFor bucle * ngFor a través de él y construir una lista para nosotros.

Vea el ejemplo de implementación basada en promesas en Plunker


Donde los observables realmente brillan

Cambiemos nuestro código para no martillar el punto final con cada pulsación de tecla, sino que solo enviaremos una solicitud cuando el usuario dejó de escribir durante 400 ms

Para revelar tales superpoderes, primero necesitamos obtener un Observable<string> que contenga el término de búsqueda que el usuario escribe. En lugar de enlazar manualmente al evento keyup, podemos aprovechar la directiva formControl de Angular . Para usar esta directiva, primero necesitamos importar el ReactiveFormsModule en nuestro módulo de aplicación.

app.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { JsonpModule } from '@angular/http';
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [BrowserModule, JsonpModule, ReactiveFormsModule]
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

Una vez importado,podemos usar el formControl desde nuestra plantilla y ponerle el nombre de "término".

<input type="text" [formControl]="term"/>

En nuestro componente, creamos una instancia de FormControl desde @angular/form y la exponemos como un campo bajo el término de nombre en nuestro componente.

Detrás de escena, el término expone automáticamente un Observable<string> como cambio de valor de propiedad valueChanges que podemos suscribirnos. Ahora que tenemos un Observable<string> , superar la entrada del usuario es tan fácil como llamar a debounceTime(400) en nuestro Observable . Esto devolverá un nuevo Observable<string> que solo emitirá un nuevo valor cuando no haya habido nuevos valores durante 400 ms.

export class App {
  items: Array<string>;
  term = new FormControl();
  constructor(private wikipediaService: WikipediaService) {
    this.term.valueChanges
              .debounceTime(400)        // wait for 400ms pause in events
              .distinctUntilChanged()   // ignore if next search term is same as previous
              .subscribe(term => this.wikipediaService.search(term).then(items => this.items = items));
  }
}

Sería un desperdicio de recursos enviar otra solicitud de un término de búsqueda para el que nuestra aplicación ya muestra los resultados. Todo lo que tenemos que hacer para lograr el comportamiento deseado es llamar al operador distinctUntilChanged justo después de llamar a debounceTime(400)

Vea el ejemplo de implementación observable en Plunker

Para tratar las respuestas fuera de orden, consulte el artículo completo http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

En cuanto al uso de Http en Angular,estoy de acuerdo en que en los casos de uso normal no hay mucha diferencia cuando se usa Observable over Promise.Ninguna de las ventajas son realmente relevantes aquí en la práctica.Espero poder ver algún caso de uso avanzado en el futuro :)


Aprende más.




Answer 3 Alireza


Tanto Promises como Observables nos ayudarán a trabajar con las funcionalidades asincrónicas en JavaScript. Son muy similares en muchos casos, sin embargo, todavía hay algunas diferencias entre los dos, las promesas son valores que se resolverán de manera asynchronous como las llamadas http . Por otro lado, los observables tratan con una secuencia de eventos asincrónicos . Las principales diferencias entre ellos se enumeran a continuación:

promise:

  • teniendo una tubería
  • normalmente sólo se usa con el retorno de datos asíncronos
  • no es fácil de cancelar

observable:

  • son anulables
  • son re-tratables por naturaleza,como reintentar y reintentar cuando
  • datos de flujo en múltiples tuberías
  • teniendo operaciones de tipo "array" como mapa,filtro,etc.
  • puede ser creado a partir de otras fuentes como eventos
  • son funciones,que podrían suscribirse más adelante

Además,he creado la imagen gráfica para que puedas ver las diferencias visualmente:

Promises and Observables image




Answer 4 Aravind


Promises

  1. Definición: lo ayuda a ejecutar funciones de forma asincrónica y a usar sus valores de retorno (o excepciones) pero solo una vez cuando se ejecuta.
  2. No es perezoso
  3. No se puede cancelar (Hay bibliotecas de Promise que soportan la cancelación,pero ES6 Promise no lo hace hasta ahora).Las dos posibles decisiones son
    • Reject
    • Resolve
  4. No se puede volver a intentar (las promesas deben tener acceso a la función original que devolvió la promesa de tener una capacidad de reintento, lo cual es una mala práctica)

Observables

  1. Definición: lo ayuda a ejecutar funciones de forma asincrónica y a usar sus valores de retorno en una secuencia continua ( varias veces ) cuando se ejecuta.
  2. Por defecto,es Perezoso ya que emite valores cuando el tiempo avanza.
  3. Tiene muchos operadores lo que simplifica el esfuerzo de codificación.
  4. Un reintento de operador se puede usar para reintentar cuando sea necesario, también si necesitamos reintentar lo observable en función de algunas condiciones . se puede usar.

    Nota : Una lista de operadores junto con sus diagramas interactivos está disponible aquí en RxMarbles.com




Answer 5 besserwisser


Hay una desventaja de los Observables que falta en las respuestas.Las promesas permiten usar las funciones de asincronización/espera del ES7.Con ellas puedes escribir código asíncrono como si fuera una llamada a una función síncrona,así que ya no necesitas devoluciones de llamada.La única posibilidad para los Observables de hacer esto,es convertirlos en Promesas.Pero cuando los conviertes a Promesas,sólo puedes tener un valor de retorno de nuevo:

async function getData(){
    const data = await observable.first().toPromise();
    //do stuff with 'data' (no callback function needed)
}

Lectura adicional: ¿Cómo puedo `esperar 'en un Rx Observable?