Promesse vs Observable
18 réponses
promesse
Un "151900920 des" poignées événement unique lorsqu'une opération asynchrone se termine ou échoue.
Note: il existe des bibliothèques Promise
qui prennent en charge l'Annulation, mais ES6 Promise
ne le fait pas jusqu'à présent.
Observables
Un Observable
est comme un Stream
(en plusieurs langues) et permet de passer zéro ou plus d'événements où le rappel est appelé pour chaque événement.
souvent Observable
est préférable à Promise
parce qu'il fournit les caractéristiques de Promise
et plus. Avec Observable
cela n'a pas d'importance si vous voulez gérer 0, 1, ou plusieurs événements. Vous pouvez utiliser la même API dans chaque cas.
Observable
a également l'avantage sur Promise
d'être annulable . Si le résultat D'une requête HTTP vers un serveur ou une autre opération asynchrone coûteuse n'est plus nécessaire, le Subscription
d'un Observable
permet d'annuler l'abonnement, tandis qu'un Promise
appellera éventuellement le succès ou l'échec de rappel même si vous n'avez plus besoin de la notification ou du résultat qu'elle fournit.
Observables "fournit des 1519200920" opérateurs comme map
, forEach
, reduce
, ... similaire à un tableau
il y a aussi des opérateurs puissants comme retry()
, ou replay()
,... qui sont souvent tout à fait à portée de main.
Promesses:
- retourner une seule valeur
- non annulable
- code plus lisible avec try / catch et async /wait
Observables:
- travailler avec des valeurs multiples au fil du temps
- annulable
- carte support, filtre, réduire et opérateurs similaires
- utiliser des Extensions réactives (RxJS)
- un tableau dont les éléments arrivent de façon asynchrone au fil du temps
les deux Promises
et Observables
nous fournissent des abstractions qui nous aident à traiter la nature asynchrone de nos applications. La différence entre eux a été clairement mise en évidence par @Günter et @Relu.
Puisqu'un extrait de code vaut mille mots, laissez passer l'exemple ci-dessous pour les comprendre plus facilement.
Merci @Christoph Burgdorf, pour le génial article
Angulaire utilise Rx.js Observables au lieu de promesses pour traiter avec HTTP.
supposons que vous construisez une fonction de recherche qui devrait instantanément afficher les résultats que vous dactylographiez. Cela semble familier, mais cette tâche comporte de nombreux défis.
- Nous ne voulons pas frapper le point d'arrêt du serveur à chaque fois l'utilisateur appuie sur une touche, elle devrait les inonder d'une tempête de demandes
HTTP
. Fondamentalement, nous voulons seulement frapper une fois que l'Utilisateur a cessé de taper au lieu de chaque touche. - Ne touchez pas l'extrémité de la recherche avec le même params de requête pour les requêtes subséquentes.
- traite des réponses hors-service. Lorsque nous avons plusieurs demandes en vol dans le même temps, nous devons tenir compte des cas où ils reviennent ordre inattendu. Imaginez que nous tapons d'abord ordinateur , arrêt, une demande Sort, nous tapons voiture , arrêt, une demande Sort. Maintenant, nous avons deux demandes en vol. Malheureusement, la demande qui transporte les résultats pour ordinateur après la demande qui transporte les résultats pour voiture .
la démo se composera simplement de deux fichiers: app.ts
et wikipedia-service.ts
. Dans un scénario réel, nous aurions probablement diviser encore plus les choses, cependant.
ci-dessous est basé sur la promesse implémentation qui ne traite aucun des cas de bord 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 service Jsonp
pour faire une GET
requête contre le API Wikipédia avec un terme de recherche donné. Notez que nous appelons toPromise
pour passer d'un Observable<Response>
à un Promise<Response>
. Finalement finir avec un Promise<Array<string>>
comme le 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 une surprise ici non plus. Nous injectons notre WikipediaService
et exposons sa fonctionnalité via une méthode de recherche au modèle. Le modèle se lie simplement à keyup et appelle search(term.value)
.
nous déroulons le résultat de la promesse que la méthode de recherche du WikipediaService retourne et l'expose comme un simple tableau de chaînes au modèle de sorte que nous puissions avoir *ngFor
boucle à travers elle et construire une liste pour nous.
Voir l'exemple de Promesse "basé sur 1519370920" mise en œuvre sur Plunker
Où Observables briller
changeons notre code pour ne pas marteler le point final avec chaque touche, mais seulement envoyer une demande lorsque l'Utilisateur a cessé de taper pour 400 ms
pour dévoiler ces super pouvoirs, nous devons d'abord obtenir un Observable<string>
qui porte le terme de recherche que l'utilisateur tape. Au lieu de se lier manuellement à l'événement keyup, nous pouvons profiter de La directive formControl
d'Angular. Pour utiliser cette directive, Nous devons d'abord importer le 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 à partir de notre modèle et le définir au nom "term".
<input type="text" [formControl]="term"/>
dans notre component, nous créons une instance de FormControl
de @angular/form
et l'exposons comme un champ sous le nom de terme sur notre component.
Derrière les coulisses terme automatiquement expose une Observable<string>
propriété valueChanges
que l'on peut s'abonner à. Maintenant que nous avons un Observable<string>
, surmonter l'entrée de l'utilisateur est aussi facile que d'appeler debounceTime(400)
sur notre Observable
. Ceci retournera un nouveau Observable<string>
qui n'émettra une nouvelle valeur que s'il n'y a pas eu de nouvelles valeurs pour 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));
}
}
Ce serait un gaspillage de ressources de envoyer une autre demande pour un terme de recherche que notre app montre déjà les résultats. Tout ce que nous avons à faire pour obtenir le comportement désiré est d'appeler l'opérateur distinctUntilChanged
juste après avoir appelé debounceTime(400)
Voir l'exemple de Observables mise en œuvre sur Plunker
pour traiter les réponses hors-service, s'il vous plaît vérifier 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 en angle, je suis d'accord que dans les cas d'utilisation normale il n'y a pas beaucoup de différence lors de L'utilisation Observable sur promesse. Aucun de ces avantages n'est vraiment pertinent dans la pratique. J'espère que je peut voir des cas d'utilisation dans le futur :)
en savoir plus
les deux promesses et Observables nous aideront à travailler avec les fonctionnalités asynchrones en JavaScript. Ils sont très similaires dans de nombreux cas, cependant, il y a encore quelques différences entre les deux ainsi, les promesses sont des valeurs qui se résoudront dans asynchronous
des façons comme appels http . D'autre part, les observables traitent de la séquence des événements asynchrones . Les principales différences sont les suivantes:
promesse:
- ayant une canalisation
- ne s'utilise généralement qu'avec le retour de données async
- pas facile à annuler
observables:
- sont annulables
- sont récupérables par nature tels que le ré-essai et le ré-essai lorsque
- flux de données dans de multiples pipe lines
- ayant des opérations de type tableau comme map, filter etc
- peut être créé à partir d'autres sources comme des événements
- ils sont fonction, qui pourrait être souscrite plus tard
en outre, j'ai créé l'image graphique pour vous ci-dessous pour montrer les différences visuellement:
promesses
- définition : vous aide à exécuter des fonctions de manière asynchrone, et à utiliser leurs valeurs de retour (ou exceptions) mais une seule fois lorsqu'il est exécuté.
- Pas Paresseux
- non annulable. Les deux décisions possibles sont
- rejet
- Résoudre
- ne peut pas être retentée (Promesses devraient avoir accès à la fonction d'origine qui a renvoyé la promesse afin d'avoir une possibilité de relance, ce qui est une mauvaise pratique)
Observables
- définition : vous aide à exécuter des fonctions de manière asynchrone, et à utiliser leurs valeurs de retour dans une séquence continue ( plusieurs fois ) lorsqu'il est exécuté.
- Par défaut, il est Paresseux comme il émet des valeurs lorsque le temps progresse.
- a beaucoup d'opérateur qui simplifie l'effort de codage.
-
one operator Rety peut être utilisé pour Rety lorsque jamais nécessaire, même si nous avons besoin de Rety l'observable basé sur certaines conditions retywhen peut être utilisé.
Note : une liste des opérateurs ainsi que leurs diagrammes interactifs est disponible ici RxMarbles.com
il manque un inconvénient dans les réponses. Les promesses permettent d'utiliser les fonctions async/attente ES7. Avec eux, vous pouvez écrire du code asynchrone comme si c'était un appel de fonction synchrone, donc vous n'avez plus besoin de callbacks. La seule possibilité pour les Observables de faire cela, est de les convertir en promesses. Mais quand vous les convertissez en promesses, vous ne pouvez avoir qu'une seule valeur de retour:
async function getData(){
const data = await observable.first().toPromise();
//do stuff with 'data' (no callback function needed)
}
autre lecture: Comment puis-je "attendre` sur un Rx Observable?
les promesses et les Observables les deux sont de la manipulation de l'appel asynchrone.trouvez ci-dessus image pour la différence principale.
Même si cette réponse est tardive, j'ai résumé les différences ci-dessous,
Observables:
- Observable est juste un
function
qui prendan observer
et renvoie unfunction Observer: an object with next, error.
- permet à L'observateur de
subscribe/unsubscribe
à son flux de données, émettre valeur suivante pour l'observateur,notify
l'observateur à propos deerrors
et informer l'observateur de lastream completion
- fournit un observateur
function to handle next value
,erreurs et fin du flux (événements ui,réponses http, données avec sockets web). - Travaille avec
multiple values
au fil du temps - Il est
cancel-able/retry-able
et supporte des opérateurs tels quemap,filter,reduce
etc. - créer un Observable peut être
-
Observable.create()
- renvoie Observable qui peut invoquer des méthodes sur -Observer Observable.from()
- convertit un tableau ou itérable en -Observable Observable.fromEvent()
- convertit un événement en Observable -Observable.fromPromise()
- convertit une Promesse en Observable -Observable.range()
- renvoie une séquence d'entiers dans la plage spécifiée
promesse :
-
une promesse représente une tâche qui se terminera à l'avenir;
-
les promesses deviennent
resolved by a value
; -
promesses obtenir rejetée par des exceptions;
-
Pas
cancellable
et il retournea single value
-
une promesse expose une fonction
(then)
- retourne alors un nouveau
promise
;- permet le
attachment
de qui sera exécuté sur la base d'state
;-
handlers
sontguaranteed
à exécuter enorder attached
;
je viens de traiter d'une question Où les promesses étaient la meilleure solution, et je le partage ici pour quiconque trébuchant à travers cette question dans le cas où il est utile (c'était exactement la réponse que je cherchais plus tôt):
dans un projet Angular2 j'ai un service qui prend quelques paramètres et renvoie une liste de valeurs pour remplir les menus déroulants sur un formulaire. Lorsque le composant form initialise, je dois appeler le même service plusieurs fois avec des paramètres différents. pour définir un certain nombre de différents menus déroulants, cependant si je mets simplement en file d'attente toutes les variables pour appeler le service, seul le dernier réussit et l'erreur du reste. La récupération de service à partir de la base de données ne pouvait traiter qu'une seule demande à la fois.
la seule façon de remplir avec succès toutes les variables du menu déroulant était d'appeler le service d'une manière qui empêchait le traitement d'une nouvelle demande jusqu'à ce que la dernière demande soit terminée, et la promesse / .alors mécanisme résolu le problème joliment.
fetchValueList(listCode): Promise<any> {
return this.dataSvc.getValueList(listCode, this.stateSvc.currentContext, this.stateSvc.currentLanguageCode)
.map(response => response.json())
.toPromise();
}
initializeDropDowns() {
this.fetchValueList('First-Val-List')
.then(data => {
this.firstValList = data;
return this.fetchValueList('Second-Val-List')
}).then(data => {
this.secondValList = data;
return this.fetchValueList('Third-Val-List')
}).then(data => {
this.thirdValList = data;
}) }
j'ai défini les fonctions dans le composant, puis appelé initializeDropDowns() dans ngOnInit.
la fonction fetchValueList retourne une promesse, donc le premier appel passe le premier listCode et lorsque la promesse se résout, la valeur de retour est dans la variable de données dans le .ensuite, bloquez où nous pouvons l'affecter au ceci.firstValList variable. Comme la fonction a retourné des données, nous savons que le service a terminé et il est sûr d'appeler à nouveau avec la deuxième listCode, la valeur de retour est dans la variable de données dans la prochaine .alors bloquez et nous l'assignons au ceci.secondValList variable.
nous pouvons enchaîner cela autant de fois que nécessaire pour remplir toutes les variables, et sur le dernier bloc de code nous omettons simplement la déclaration de retour et le bloc se termine.
c'est un cas d'utilisation très spécifique où nous avons un seul service qui doit être appelé plusieurs fois comme le composant initialise, et où le service doit compléter son fetch et retourner une valeur avant de pouvoir être appelé à nouveau, mais dans ce cas, la promesse / .alors la méthode était idéale.
je crois que toutes les autres réponses devraient dissiper vos doutes. Néanmoins, je voulais juste ajouter que les observables sont basés sur la programmation fonctionnelle, et je trouve très utiles les fonctions qui l'accompagnent comme map, flatmap, reduce, zip. La cohérence que le web atteint surtout quand il dépend des requêtes API est une amélioration brutale.
je recommande fortement cette documentation , car c'est la documentation officielle de réactivex et Je trouve que c'est le plus clair.
si vous voulez entrer dans observables je suggérerais ce post de 3partie: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1 /
bien qu'il soit destiné à RxJava, les concepts sont les mêmes, et il est vraiment bien expliqué. Dans la documentation de réactivex vous avez les équivalences pour chaque fonction. Vous devez chercher RxJS.
J'espère que cela aide, juste essayé contribuer ici. :)
Observables vs promesses
Promises et Observables , tous deux nous fournissent une façon simple qui nous aide à lutter contre la nature asynchrone de nos applications. Toutefois, il existe des différences importantes entre les deux:
- Observables peut définir à la fois la configuration et les aspects de démontage comportement asynchrone.
- Observables sont annulables.
- de plus, Observables peut être récupéré en utilisant l'un des opérateurs de Rety fournis par L'API, tels que Rety et retywhen. D'un autre côté, les promesses exigent que l'appelant ait accès à la fonction originale qui a retourné la promesse afin d'avoir une capacité de Ré-essai.
les Promesses de l'application effective de cette sémantique. Vous pouvez créer une Promesse, qui se résout avec une certaine valeur:
const numberPromise = new Promise((resolve) => {
resolve(5);
});
numberPromise.then(value => console.log(value));
// will simply print 5
mais tenter de résoudre la promesse à nouveau avec une autre valeur échouera. La promesse est toujours résolue avec la première valeur transmise à la fonction resolve et ignore les appels ultérieurs à elle:
const numberPromise = new Promise((resolve) => {
resolve(5);
resolve(10);
});
numberPromise.then(value => console.log(value));
// still prints only 5
au contraire, les Observables vous permettent de résoudre (ou, comme on dit," d'émettre") des valeurs multiples. Voici à quoi ça ressemblerait:
const numberObservable = new Observable((observer) => {
observer.next(5);
observer.next(10);
});
numberObservable.subscribe(value => console.log(value));
// prints 5 and 10
notez à quel point la syntaxe est similaire - nous avons changé la promesse à Observable, remplacé résoudre la fonction avec observateur.appel suivant et à la place de puis utilisé subscribe, qui se comporte très similaire.
promesse:
- fournissent une seule valeur future;
- pas paresseux;
- non annulable;
Observables:
- Émet plusieurs valeurs au fil du temps;
- Paresseux;
- annulable;
- supporte les opérateurs map, filter, reduce et similaires
vous pouvez utiliser promet à la place des observables lors de L'appel de HTTP en Angular si vous le souhaitez.
promesse-fournir une seule valeur future. Pas paresseux . Pas capables d'annulation. Il va les rejeter ou de les résoudre.
Observables - Fournir des multiples de valeur d'avenir. Paresseux. Capables d'annulation . Il fournit d'autres méthodes live map,filtrer,réduire.
vue d'ensemble:
- les promesses et les Observables nous aident à traiter les opérations asynchrones. Ils peuvent appeler certains callbacks lorsque ces opérations asynchrones sont effectuées.
- Une Promesse ne peut gérer qu'un seul événement, sont Observables pour des flux d'événements au fil du temps
- Promet ne peut pas être annulée une fois qu'ils sont en attente
- Données Observables émettent peut transformés à l'aide des opérateurs
vous pouvez toujours utiliser un observable pour traiter le comportement asynchrone depuis un observable a la fonctionnalité d'une promesse. Cependant, il arrive parfois que cette fonctionnalité supplémentaire offerte par les Observables ne soit pas nécessaire. Ce serait donc un surcoût pour importer une bibliothèque afin de l'utiliser.
quand utiliser les promesses:
utilisez des promesses Quand vous avez un simple opération async de que vous souhaitez traiter le résultat. Par exemple:
var promise = new Promise((resolve, reject) => {
// do something once, possibly async
// code inside the Promise constructor callback is getting executed synchronously
if (/* everything turned out fine */) {
resolve("Stuff worked!");
}
else {
reject(Error("It broke"));
}
});
//after the promise is resolved or rejected we can call .then or .catch method on it
promise.then((val) => console.log(val)) // logs the resolve argument
.catch((val) => console.log(val)); // logs the reject argument
ainsi une promesse exécute un code où elle résout ou rejette. Si résoudre ou rejeter est appelé la promesse va d'un état en attente à soit un résolu ou rejeté état. Lorsque l'état de promesse est résolu, la méthode then()
est appelée. Lorsque l'état de promesse est rejeté, la méthode catch()
est appelé.
quand utiliser les Observables:
utilisez Observables quand il ya un flux au fil du temps qui vous devez être manipulés. Dans L'Observable lui-même est spécifié quand l'événement suivant s'est produit, quand une erreur se produit, ou quand L'Observable est terminé. Nous pouvons ensuite nous abonner à cet observable, qui l'active et dans cet abonnement nous pouvons passer en 3 callbacks (ne pas toujours avoir à passer en tout). Un callback à exécuter pour le succès, un callback pour erreur, et un rappel pour complétion. Par exemple:
const observable = Rx.Observable.create(observer => {
// create a single value and complete
observer.onNext(1);
observer.onCompleted();
});
source.subscribe(
x => console.log('onNext: %s', x), // success callback
e => console.log('onError: %s', e), // error callback
() => console.log('onCompleted') // completion callback
);
// first we log: onNext: 1
// then we log: onCompleted
lors de la création d'un observable il nécessite une fonction de rappel qui fournit un observateur comme argument. Sur cet observateur vous pouvez alors appeler onNext
, onCompleted
, onError
. Ensuite, lorsque L'Observable est abonné, il appellera les callbacks correspondants passés dans l'abonnement.
Observables et promesses fournissent tous deux un moyen de travailler avec async activités en JavaScript. Alors que les promesses soit rejeter / résoudre basé sur l'achèvement d'un seul événement asynchrone (requête http), Observables peuvent émettre en continu des changements d'état basés sur les observateurs qui s'y abonnent.
une différence fondamentale entre eux est que l'observable fournit des moyens de annuler a demande et renvoyer un nouveau. Où comme promesse ne permettent pas une telle caractéristique.
aussi, Promise émet une seule valeur alors que Observable émet plusieurs valeurs. Ainsi, lors du traitement D'une requête HTTP, Promise peut gérer une seule réponse pour la même requête, mais que se passe-t-il s'il y a plusieurs réponses à la même requête, alors nous devons utiliser Observable.
brève réponse:
Observables est mieux , il a tous les Promesses fonctions et fonctionnalités supplémentaires.
longue réponse:
promesses:
- à Usage unique "Retour les données une seule fois" "1519250920 de Non-annulation 1519260920"
- auditeur
- Pas De Prise En Charge D'Un Auditeur
Observables:
- Renvoyer les Données autant de fois que les données de changement
- Soutien annuler
- support socket
- Soutien de nombreux Auditeur et de lui notifier lors de changement des données
- Carte de soutien, filtre ,réduire
il y a déjà beaucoup de réponses à ce sujet, donc je ne voudrais pas en ajouter une redondante.
mais pour quelqu'un qui vient de commencer à apprendre Observable / Angular et se demande lequel utiliser comparer avec promesse , je vous recommande de garder tout Observable et de convertir toutes les promesses existantes dans votre projet à Observable.
simplement parce que le cadre angulaire lui-même et C'est la communauté qui utilise Observable. Il serait donc avantageux d'intégrer des services-cadres ou des modules tiers et de tout assembler.
bien que j'apprécie toutes les notes négatives, mais j'insiste toujours sur mon opinion ci-dessus à moins que quelqu'un ne mette un commentaire approprié pour énumérer quelques scénarios qui pourraient encore être utiles dans votre projet angulaire d'utiliser des promesses sur Observables.
bien sûr, aucune opinion est 100% correct dans tous les cas, mais au moins je pense que 98% du temps pour les projets commerciaux réguliers mis en œuvre dans un cadre angulaire, Observable est la bonne voie à suivre.
même si vous ne l'aimez pas au point de départ de votre projet de passe-temps simple, vous réaliserez bientôt presque tous les composants avec lesquels vous interagissez en angle, et la plupart du cadre de tierce partie amical angulaire utilisent Observables, et alors vous finirez par convertir constamment votre promesse à Observable afin de communiquer avec eux.
Ces composants inclus, mais non limité à: HttpClient, générateur de Formulaire, Angulaire matériel modules/dialogues, Ngrx store/effets et ngx-bootstrap.
en fait, la seule promesse de L'écosystème angulaire dont j'ai parlé au cours des deux dernières années est APP_INITIALIZER
.
expliquer en référence des appels Http angulaires pour L'Api à distance: Promesses est utilisé pour maintenir l'état des appels asynchrones. un les données sont obtenues à partir de l'Api à distance et montrent en vue
et dans Observable proviennent du modèle observable et introduire par Rxjs quand il vous donne la possibilité de mettre à jour les données plusieurs fois dans le flux comme données observables.