Quelle est la différence entre Promise
et Observable
dans Angular ?
Un exemple sur chacun serait utile pour comprendre les deux cas. Dans quel scénario pouvons-nous utiliser chaque cas ?
Quelle est la différence entre Promise
et Observable
dans Angular ?
Un exemple sur chacun serait utile pour comprendre les deux cas. Dans quel scénario pouvons-nous utiliser chaque cas ?
Promesse
Une Promesse
gère un événement unique lorsqu'une opération asynchrone est terminée ou échoue.
Remarque : Il existe des bibliothèques de Promesse
qui prennent en charge l'annulation, mais l'ES6 Promesse
ne le fait pas pour le moment.
Observable
Un Observable
est comme un Stream
(dans de nombreuses langues) et permet de transmettre zéro ou plusieurs événements où le rappel est appelé pour chaque événement.
Il est souvent préférable d'utiliser un Observable
plutôt qu'une Promesse
car il offre les fonctionnalités de la Promesse
et bien plus encore. Avec un Observable
, cela n'a pas d'importance si vous souhaitez gérer 0, 1 ou plusieurs événements. Vous pouvez utiliser la même API dans chaque cas.
Observable
a également l'avantage par rapport à la Promesse
d'être annulable. Si le résultat d'une requête HTTP vers un serveur ou toute autre opération asynchrone coûteuse n'est plus nécessaire, l'Abonnement
d'un Observable
permet d'annuler l'abonnement, tandis qu'une Promesse
appellera finalement le rappel de réussite ou d'échec même lorsque vous n'avez plus besoin de la notification ou du résultat qu'elle fournit.
Alors qu'une Promesse
démarre immédiatement, un Observable
ne démarre que si vous vous y abonnez. C'est pourquoi les Observables sont appelés paresseux.
L'Observable fournit des opérateurs comme map
, forEach
, reduce
, ... similaire à un tableau
Il existe également de puissants opérateurs comme retry()
, ou replay()
, ... qui sont souvent très pratiques. Une liste d'opérateurs fournis avec rxjs
L'exécution paresseuse permet de construire une chaîne d'opérateurs avant que l'observable ne soit exécuté par abonnement, pour réaliser une programmation plus déclarative.
Alors, y a-t-il une bonne raison d'utiliser Promise au lieu d'Observable dans le cas d'un seul rappel, ou bien les Observables devraient-ils également être utilisés puisqu'ils peuvent fonctionner de cette manière ? En gros, est-il bon de pratiquer le "Observable all the things" ou Promise a-t-il toujours sa place ?
Si vous voulez utiliser le style réactif, il vous suffit d'utiliser des observables partout. Si vous avez uniquement des observables, vous pouvez facilement les composer. Si vous les mélangez, ce n'est plus aussi propre. Si le style réactif ne vous importe pas, vous pouvez utiliser des promesses pour des événements ponctuels où vous ne vous souciez pas de l'annulation et des observables pour des flux d'événements.
Pour une bonne ressource d'introduction sur Observables/RxJs/Programmation Réactive : gist.github.com/staltz/868e7e9bc2a7b8c1f754 ("L'introduction à la Programmation Réactive que vous avez manquée")
Les deux sites Promises
et Observables
nous fournissent des abstractions qui nous aident à faire face aux asynchrone la nature de nos applications. La différence entre les deux a été clairement soulignée par @Günter et @Relu.
Puisqu'un extrait de code vaut mille mots, examinons l'exemple ci-dessous pour mieux les comprendre.
Merci @Christoph Burgdorf pour l'incroyable article
Angular utilise les Observables de Rx.js au lieu des promesses pour traiter le HTTP.
Supposons que vous construisiez un fonction de recherche qui devrait vous montrer instantanément les résultats au fur et à mesure que vous tapez. Cela vous semble familier, mais cette tâche comporte de nombreux défis.
HTTP
demandes. En fait, nous ne voulons l'activer qu'une fois que l'utilisateur a arrêté de taper au lieu de le faire à chaque frappe.La démo sera simplement constituée de deux fichiers : app.ts
et wikipedia-service.ts
. Dans un scénario réel, il est plus que probable que l'on divise davantage les choses, cependant.
Vous trouverez ci-dessous Basé sur des promesses qui ne gère aucun des cas limites décrits.
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]);
}
}
Nous injectons le Jsonp
pour faire un GET
contre le API Wikipedia avec un terme de recherche donné. Notez que nous appelons toPromise
afin de passer d'un Observable<Response>
à un Promise<Response>
. Vous finissez par vous retrouver avec un Promise<Array<string>>
comme type de retour de notre méthode de recherche.
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);
}
}
Pas vraiment de surprise ici non plus. Nous injectons notre WikipediaService
et exposer sa fonctionnalité via une méthode de recherche dans le modèle. Le modèle se lie simplement à keyup et appelle search(term.value)
.
Nous déballons le résultat de la Promesse que la méthode de recherche du WikipediaService renvoie et de l'exposer comme un simple tableau de chaînes de caractères au modèle de sorte que nous puissions avoir *ngFor
le parcourir en boucle et nous faire une liste.
Voir l'exemple de Basé sur des promesses la mise en œuvre sur Plunker
Où Observables briller vraiment
Modifions notre code pour que le point de terminaison ne soit pas sollicité à chaque frappe, mais qu'il n'envoie une requête que lorsque l'utilisateur a cessé de taper pendant deux secondes. 400 ms
Pour dévoiler de tels super pouvoirs, nous devons d'abord obtenir un Observable<string>
qui porte le terme de recherche que l'utilisateur a tapé. Plutôt que de se lier manuellement à l'événement keyup, nous pouvons tirer parti de la fonction d'Angular formControl
directive. Pour utiliser cette directive, nous devons tout d'abord importer la directive ReactiveFormsModule
dans notre module d'application.
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 {}
Une fois importé, nous pouvons utiliser formControl dans notre modèle et lui attribuer le nom "term".
<input type="text" [formControl]="term"/>
Dans notre composant, nous créons une instance de FormControl
de @angular/form
et l'exposer comme un champ sous le nom de terme sur notre composant.
Dans les coulisses, terme expose automatiquement un Observable<string>
comme propriété valueChanges
à laquelle nous pouvons nous abonner. Maintenant que nous avons un Observable<string>
pour surmonter l'entrée de l'utilisateur, il suffit d'appeler debounceTime(400)
sur notre Observable
. Cela renverra un nouveau Observable<string>
qui n'émettra une nouvelle valeur que s'il n'y a pas eu de nouvelles valeurs pendant 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));
}
}
Ce serait un gaspillage de ressources que d'envoyer une autre demande pour un terme de recherche dont notre application affiche déjà les résultats. Tout ce que nous avons à faire pour obtenir le comportement souhaité est d'appeler la commande distinctUntilChanged
juste après avoir appelé debounceTime(400)
Voir l'exemple de Observable la mise en œuvre sur Plunker
Pour traiter les réponses non ordonnées, veuillez consulter l'article complet. http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
Dans la mesure où j'utilise Http dans Angular, je suis d'accord pour dire que dans les cas d'utilisation normaux, il n'y a pas beaucoup de différence entre Observable et Promise. Aucun des avantages n'est vraiment pertinent ici en pratique. J'espère que je pourrai voir des cas d'utilisation avancés à l'avenir :)
En savoir plus
Je ne suis pas entièrement convaincu par la décision de transformer le service Http en Observable. Chaque explication que j'entends repose sur le même exemple : la recherche par terme. Mais cela concerne la gestion des événements du navigateur. J'aimerais savoir quel avantage il y a à l'appliquer lors du traitement des requêtes http asynchrones.
@AlexPollan, il y a en fait une bonne explication des avantages du service http renvoyant un observable sur ce podcast avec Ben Lesh: devchat.tv/js-jabber/…. En fin de compte, le principal avantage est que vous pouvez annuler un observable, et un cas d'utilisation pour cela est décrit dans le lien ci-dessus - bien que un peu artificiel - est que si vous appelez plusieurs apis et ne vous intéressez qu'à la première réponse, peu importe lequel des api vous avez appelé vous répond en premier, vous pouvez ensuite annuler les demandes aux autres.
À la fois les Promesses et les Observables nous aideront à travailler avec les fonctionnalités asynchrones en JavaScript. Ils sont très similaires dans de nombreux cas, cependant, il existe encore quelques différences entre les deux, les promesses sont des valeurs qui se résoudront de manière asynchrone
comme les appels HTTP. D'autre part, les observables traitent une séquence d'événements asynchrones. Les principales différences entre eux sont répertoriées ci-dessous :
Promesse :
Observable :
Aussi, j'ai créé l'image graphique pour vous ci-dessous pour montrer les différences visuellement :
Oui, il y a aussi un moyen de les annuler... certaines personnes utilisent bluebird ou des bibliothèques tierces... en utilisant la bibliothèque Q dans Angular il y a des moyens de l'annuler... mais comme je l'ai dit pas très pratique
Avoir un pipeline a parfois des avantages, par exemple dans APP_INITIALIZER, s'il y a plusieurs pipelines, il arrive parfois qu'il ne puisse jamais se terminer ou se termine plusieurs fois.
Il y a un inconvénient des Observables manquant dans les réponses. Les Promises permettent d'utiliser les fonctions async/await ES7. Avec elles, vous pouvez écrire du code asynchrone comme s'il s'agissait d'un appel de fonction synchrone, donc vous n'avez plus besoin de rappels. La seule possibilité pour les Observables de le faire est de les convertir en Promises. Mais lorsque vous les convertissez en Promises, vous ne pouvez avoir qu'une seule valeur de retour à nouveau :
async function getData(){
const data = await observable.first().toPromise();
//do stuff with 'data' (no callback function needed)
}
Lire la suite : Comment puis-je `attendre` sur un Rx Observable ?
Aussi surpris pourquoi personne n'a souligné cet avantage énorme des Promesses - la simplicité et la transparence grâce à async/await. J'ai basculé vers les Promesses juste pour la possibilité d'écrire un code plat. La logique métier simple et le code d'interaction utilisateur ne devraient pas ressembler à de la science de la fusée et être pollués par l'enfer imbriqué des extensions réactives. De plus, async/await n'est pas seulement pour l'avenir, vous pouvez l'utiliser dans des applications de production publiques maintenant en utilisant des transpileurs. J'utilise TypeScript 2.3 et c'est génial, comme un vrai langage.
Agréable, mais penser de manière réactive et tout avec les RxOperators, peut-être que ce n'est pas une fonctionnalité révolutionnaire.
Je utilise Promise async/await tout le temps et c'est vraiment puissant. Il offre une familiarité et une clarté du code tout en utilisant un vrai moteur javascript asynchrone. En revanche, les Observables sont synchrone, ils sont exécutés dans la pile d'exécution principale alors que Promise async/await utilise des fonctionnalités asynchrones en js dans le moteur : boucle d'événements, libuv, file de tâches micro etc. Rendre les Observables asynchrones en utilisant setTimeout() est idiot car cela monopolise les ressources et vous ne pouvez pas contrôler l'ordre d'exécution dans la boucle d'événements. Il utilise la partie WebAPI de la boucle d'événements, tandis que les événements dans la file de tâches micro ont la priorité.
Promesses
Observables
Remarque : Une liste d'opérateurs accompagnée de leurs diagrammes interactifs est disponible ici sur **RxMarbles.com**
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
32 votes
Je vous suggérerais de lire ce post; Promesse Angular2 vs observable
7 votes
En termes plus simples angular-2-training-book.rangle.io/handout/observables/…
5 votes
À toute personne lisant cette question-réponse - en tant que personne impliquée dans les deux mondes en tant que mainteneur, conférencier et utilisateur de longue date, je vous encourage à lire la documentation officielle de RxJS et la documentation MDN sur les promesses. Je trouve personnellement que les réponses fournies ici sont entièrement trompeuses et incorrectes et je pense qu'elles sont, bien qu'émanant de personnes essayant d'aider, très nocives.
5 votes
Je vous suggère de lire ce document officiel sur Angular angular.io/guide/comparing-observables
1 votes
Une promesse est toujours asynchrone, tandis qu'un Observable peut être soit synchrone, soit asynchrone, une promesse peut fournir une seule valeur, alors qu'un Observable est un flux de valeurs (de 0 à plusieurs valeurs), vous pouvez appliquer des opérateurs RxJS à un Observable pour obtenir un nouveau flux adapté
0 votes
Un incontournable https://youtu.be/uQ1zhJHclvs
0 votes
Le lien: mydaytodo.com/rxjs-observables-vs-javascript-promise top mu p fait un bon travail pour expliquer la différence entre les deux et dans quels scénarios appliquer au mieux les deux,