Solución:
Promesa
A Promise
maneja un Evento único cuando una operación asincrónica se completa o falla.
Nota: hay Promise
bibliotecas que admiten la cancelación, pero ES6 Promise
no hasta ahora.
Observable
Un Observable
es como un Stream
(en muchos idiomas) y permite pasar cero o más eventos donde se llama a la devolución de llamada para cada evento.
A menudo Observable
se prefiere sobre Promise
porque proporciona las características de Promise
y más. Con Observable
no importa si desea manejar 0, 1 o varios eventos. Puede utilizar la misma API en cada caso.
Observable
también tiene la ventaja sobre Promise
ser para interrumpir. Si el resultado de una solicitud HTTP a un servidor o alguna otra operación asincrónica costosa ya no se necesita, el Subscription
de un Observable
permite cancelar la suscripción, mientras que un Promise
eventualmente llamará a la devolución de llamada exitosa o fallida incluso cuando ya no necesite la notificación o el resultado que proporciona.
Mientras que un Promise
comienza inmediatamente, un Observable
solo comienza si te suscribes. Es por eso que los Observables se llaman perezosos.
Observable proporciona operadores igual que map
, forEach
, reduce
, … similar a una matriz
También hay operadores poderosos como retry()
, o replay()
, … que a menudo son bastante útiles. Una lista de operadores enviados con rxjs
La ejecución diferida permite construir una cadena de operadores antes de que se ejecute el observable mediante la suscripción, para hacer un tipo de programación más declarativa.
Ambos Promises
y Observables
proporcionarnos abstracciones que nos ayuden a lidiar con el asincrónico naturaleza de nuestras aplicaciones. La diferencia entre ellos fue señalada claramente por @ Günter y @Relu.
Dado que un fragmento de código vale más que mil palabras, revise el siguiente ejemplo para comprenderlo más fácilmente.
Gracias @Christoph Burgdorf por el increíble artículo
Angular usa Rx.js Observables en lugar de promesas para tratar con HTTP.
Suponga que está construyendo un buscando función que debería mostrarle instantáneamente los resultados 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 inundarlo con una tormenta de
HTTP
peticiones. Básicamente, solo queremos presionarlo una vez que el usuario haya dejado de escribir en lugar de con cada pulsación de tecla. - No llegues al punto final de la búsqueda con el mismos parámetros de consulta para solicitudes posteriores.
- Trate las respuestas fuera de orden. Cuando tenemos varias solicitudes en curso al mismo tiempo, debemos tener en cuenta los casos en los que regresan en un orden inesperado. Imagina que primero escribimos computadora, detente, sale una solicitud, escribimos coche, deténgase, sale una solicitud. Ahora tenemos dos solicitudes en curso. Desafortunadamente, la solicitud que lleva los resultados de computadora vuelve después de la solicitud que incluye los resultados de coche.
La demostración constará simplemente de dos archivos: app.ts
y wikipedia-service.ts
. Sin embargo, en un escenario del mundo real, lo más probable es que dividiríamos las cosas más.
A continuación es Basado en promesas implementación que no maneja ninguno de los casos extremos 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 Jsonp
servicio para hacer un GET
solicitud contra el API de Wikipedia con un término de búsqueda determinado. Note que llamamos toPromise
con el fin de obtener de un Observable<Response>
a un Promise<Response>
. Eventualmente terminará con un 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 WikipediaService
y exponer su funcionalidad a través de un método de búsqueda a la plantilla. La plantilla simplemente se une a tecla Arriba y llama search(term.value)
.
Desenvolvemos el resultado de la Promesa que el método de búsqueda de WikipediaService devuelve y lo expone como una simple matriz de cadenas a la plantilla para que podamos tener *ngFor
recorrerlo y crear una lista para nosotros.
Vea el ejemplo de Basado en promesas implementación en Plunker
Dónde Observables realmente brillar
Cambiemos nuestro código para no martillar el punto final con cada pulsación de tecla, sino que solo enviemos una solicitud cuando el usuario deje de escribir para 400 ms
Para develar tales superpoderes primero necesitamos obtener un Observable<string>
que lleva el término de búsqueda que escribe el usuario. En lugar de enlazar manualmente al evento keyup, podemos aprovechar las ventajas de Angular formControl
directiva. 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 formControl desde nuestra plantilla y configurarlo con el nombre “término”.
<input type="text" [formControl]="term"/>
En nuestro componente, creamos una instancia de FormControl
de @angular/form
y exponerlo como un campo bajo el término de nombre en nuestro componente.
Entre bastidores, término expone automáticamente un Observable<string>
como propiedad valueChanges
al que podemos suscribirnos. Ahora que tenemos un Observable<string>
, superar la entrada del usuario es tan fácil como llamar debounceTime(400)
en nuestro Observable
. Esto devolverá un nuevo Observable<string>
que solo emitirá un nuevo valor cuando no haya habido nuevos valores para 400ms.
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 una pérdida 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 distinctUntilChanged
operador justo después de que llamamos debounceTime(400)
Vea el ejemplo de Observable implementación en Plunker
Para lidiar con las respuestas fuera de orden, consulte el artículo completo http://blog.ilsttram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
En la medida en que estoy usando Http en Angular, estoy de acuerdo en que en los casos de uso normales no hay mucha diferencia al usar Observable sobre Promise. Ninguna de las ventajas es realmente relevante aquí en la práctica. Espero poder ver algún caso de uso avanzado en el futuro 🙂
Aprende más
- https://angular-2-training-book.rangle.io/handout/observables/
- https://angular.io/tutorial/toh-pt6#observables
Ambos Promesas y Observables nos ayudará a trabajar con el funcionalidades asincrónicas en JavaScript. Son muy similares en muchos casos, sin embargo, aún existen algunas diferencias entre los dos también, las promesas son valores que se resolverán en asynchronous
maneras como http llamadas. Por otro lado, los observables tratan con una secuencia de eventos asincrónicos. Las principales diferencias entre ellos se enumeran a continuación:
promesa:
- tener una tubería
- generalmente solo se usa con retorno de datos asíncronos
- no es fácil de cancelar
observable:
- son cancelables
- son repetibles por naturaleza, como reintentar y reintentar cuando
- transmitir datos en varias canalizaciones
- tener operaciones similares a matrices como mapa, filtro, etc.
- se puede crear a partir de otras fuentes como eventos
- son funciones, que se pueden suscribir más adelante
Además, he creado la imagen gráfica para ti a continuación para mostrar las diferencias visualmente: