Promesse vs Observable

Quelqu’un peut-il s’il vous plaît expliquer 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?

Promettre

Une Promise gère un événement unique lorsqu’une opération asynchrone se termine ou échoue.

Remarque: il existe des bibliothèques Promise qui prennent en charge l’annulation, mais ES6 Promise ne l’a pas encore fait.

Observable

Un Observable est comme un Stream (dans de nombreuses langues) et permet de passer zéro ou plusieurs événements où le rappel est appelé pour chaque événement.

Souvent, Observable est préféré à Promise car il fournit les fonctionnalités de Promise et plus encore. Avec Observable , peu importe si vous souhaitez gérer 0, 1 ou plusieurs événements. Vous pouvez utiliser la même API dans chaque cas.

Observable é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, la Subscription d’un Observable permet d’annuler l’abonnement, alors qu’une Promise finira par appeler le succès ou l’échec du rappel, même si vous ne le faites pas. besoin de la notification ou le résultat qu’il fournit plus.

Observable fournit des opérateurs tels que map , forEach , forEach , … similaire à un tableau

Il y a aussi des opérateurs puissants comme retry() , ou replay() , qui sont souvent très pratiques.

Promesses:

  • renvoyer une seule valeur
  • non annulable
  • code plus lisible avec try / catch et async / waiting

Observables:

  • travailler avec plusieurs valeurs au fil du temps
  • annulable
  • prise en charge des opérateurs de carte, de filtre, de réduction et similaires
  • utiliser des extensions réactives (RxJS)
  • un tableau dont les éléments arrivent de manière asynchrone dans le temps

Les Promises et les Observables nous fournissent des abstractions qui nous aident à gérer la nature asynchrone de nos applications. La différence entre eux a été clairement mise en évidence par @ Günter et @Relu.

Comme un extrait de code vaut mille mots, parcourez l’exemple ci-dessous pour les comprendre plus facilement.

Merci @Christoph Burgdorf pour l’ article génial


Angular utilise les observables Rx.js au lieu de promesses pour traiter HTTP.

Supposons que vous construisiez une fonction de recherche qui devrait vous montrer instantanément les résultats que vous tapez. Cela semble familier, mais cette tâche comporte de nombreux défis.

  • Nous ne voulons pas bash le sharepoint terminaison du serveur chaque fois que l’utilisateur appuie sur une touche, cela doit les inonder de tempête de requêtes HTTP . Fondamentalement, nous voulons seulement le bash une fois que l’utilisateur a cessé de taper au lieu de chaque frappe de touche.
  • Ne frappez pas le noeud final de recherche avec les mêmes parameters de requête pour les requêtes suivantes.
  • Traiter les réponses hors service. Lorsque nous avons plusieurs demandes en vol en même temps, nous devons tenir compte des cas où elles reviennent dans un ordre inattendu. Imaginons que nous saisissions d’abord l’ ordinateur , que nous arrêtions, qu’une demande soit émise, que nous saisissions une voiture , que nous arrêtions, qu’une demande soit émise. Nous avons maintenant deux demandes en vol. Malheureusement, la demande qui porte les résultats pour ordinateur revient après la demande qui porte les résultats pour la voiture .

La démo consistera simplement en deux fichiers: app.ts et wikipedia-service.ts . Dans un scénario réel, nous risquons fort de diviser les choses plus haut.


Ci-dessous est l’implémentation basée sur Promise qui ne gère 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: ssortingng) { 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 effectuer une requête GET sur l’API Wikipedia avec un terme de recherche donné. Notez que nous appelons toPromise afin de passer d’une Observable à une Promise . Finalement, vous Promise> un Promise> 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: ` 

Wikipedia Search

  • {{item}}
` }) export class AppComponent { items: Array; constructor(private wikipediaService: WikipediaService) {} search(term) { this.wikipediaService.search(term) .then(items => this.items = items); } }

Pas beaucoup de surprise 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 au keyup et à la search(term.value) appels search(term.value) .

Nous déballons le résultat de la promesse que la méthode de recherche de WikipediaService renvoie et l’exposons comme un simple tableau de chaînes au modèle afin que nous puissions le *ngFor boucle et créer une liste pour nous.

Voir l’exemple de l’implémentation basée sur Promise sur Plunker


Où les observables brillent vraiment

Modifions notre code pour ne pas écraser le noeud final à chaque frappe, mais plutôt envoyer une requête uniquement lorsque l’utilisateur a cessé de taper 400 ms

Pour dévoiler de telles super puissances, nous devons d’abord obtenir une Observable qui contient le terme de recherche saisi par l’utilisateur. Au lieu de se lier manuellement à l’événement keyup, nous pouvons tirer parti de la directive formControl d’Angular. Pour utiliser cette directive, vous devez 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 depuis notre modèle et le définir sous le nom de “terme”.

  

Dans notre composant, nous créons une instance de FormControl partir de @angular/form et l’exposons en tant que champ sous le terme name sur notre composant.

Dans les coulisses, le terme expose automatiquement un object Observable tant que propriété valueChanges laquelle nous pouvons nous abonner. Maintenant que nous avons une Observable , surmonter l’entrée utilisateur est aussi simple que d’appeler debounceTime(400) sur notre Observable . Cela renverra une nouvelle Observable qui n’émettra qu’une nouvelle valeur lorsqu’il n’y aura pas eu de nouvelles valeurs pour 400ms.

 export class App { items: Array; 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)); } } 

Envoyer une autre demande pour un terme de recherche pour lequel notre application affiche déjà les résultats serait un gaspillage de ressources. Tout ce que nous avons à faire pour obtenir le comportement souhaité est d’appeler l’opérateur distinctUntilChanged juste après que nous ayons appelé debounceTime(400)

Voir l’exemple de l’implémentation Observable sur Plunker

Pour traiter les réponses hors service, 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 sur le fait que dans les cas d’utilisation normale, il n’y a pas beaucoup de différence lorsque l’on utilise Observable over Promise. Aucun des avantages n’est vraiment pertinent ici dans la pratique. J’espère pouvoir voir un cas d’utilisation avancé à l’avenir 🙂


Apprendre encore plus

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 des différences entre les deux, les promesses sont des valeurs qui seront résolues de asynchronous comme les appels http . En revanche, les observables traitent de la séquence des événements asynchrones . Les principales différences sont énumérées ci-dessous:

promettre:

  • avoir une conduite
  • généralement utilisé uniquement avec le retour de données asynchrone
  • pas facile à annuler

observable:

  • sont annulables
  • sont récupérables par nature, comme réessayer et réessayerWhen
  • stream de données dans plusieurs conduites
  • avoir des opérations de type tableau comme carte, filtre, etc.
  • peut être créé à partir d’autres sources comme des événements
  • ils sont fonctionnels, ce qui pourrait être souscrit ultérieurement

J’ai également créé l’image graphique ci-dessous pour montrer les différences visuellement:

Image des promesses et des observables

Promesses

  1. Définition: vous aide à exécuter des fonctions de manière asynchrone et à utiliser leurs valeurs de retour (ou exceptions) une seule fois lorsqu’elles sont exécutées.
  2. Pas paresseux
  3. Non annulable Les deux décisions possibles sont
    • Rejeter
    • Résoudre
  4. Ne peut être réessayé (les promesses doivent avoir access à la fonction d’origine qui a renvoyé la promesse afin de pouvoir réessayer, ce qui est une mauvaise pratique)

Les observables

  1. 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’elles sont exécutées.
  2. Par défaut, il est paresseux car il émet des valeurs au fil du temps.
  3. Possède beaucoup d’opérateurs, ce qui simplifie les efforts de codage.
  4. Un nouvel essai d’ opérateur peut être utilisé pour réessayer lorsque cela est nécessaire, même si vous devez réessayer l’observable en fonction de certaines conditions, retryWhen peut être utilisé.

    Note : Une liste des opérateurs avec leurs diagrammes interactifs est disponible ici sur RxMarbles.com

Il y a un inconvénient des observables manquant dans les réponses. Les promesses permettent d’utiliser les fonctions asynchrones / d’attente de l’ES7. Avec eux, vous pouvez écrire un code asynchrone, comme ce serait un appel de fonction synchrone, vous n’avez donc plus besoin de rappels. La seule possibilité pour les observables de le faire est de les convertir en promesses. Mais lorsque vous les convertissez en Promises, 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) } 

Pour en savoir plus: Comment puis-je attendre sur un observable Rx?

Je suis un gars de la photo, cela manquait dans d’autres réponses:

entrer la description de l'image ici

Promesses vs Observables

Les promesses et les observables traitent toutes les deux l’appel asynchrone.

Même si cette réponse est tardive, j’ai résumé les différences ci-dessous,

Observable:

  1. Observable est juste une function qui prend an observer et retourne une function Observer: an object with next, error.
  2. Observer permet de subscribe/unsubscribe à son stream de données, d’émettre une valeur suivante à l’observateur, d’ notify l’observateur des errors et d’informer l’observateur de l’ stream completion du stream completion
  3. Observer fournit une function to handle next value , les erreurs et la fin du stream (événements ui, réponses http, données avec des sockets Web).
  4. Fonctionne avec multiple values fil du temps
  5. Il peut être cancel-able/retry-able et prend en charge des opérateurs tels que la map,filter,reduce etc.
  6. La création d’une observable peut être – Observable.create() – renvoie Observable pouvant invoquer des méthodes – Observer Observable.from() – convertit un tableau ou une itération 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 :

  1. Une promesse représente une tâche qui se terminera dans le futur;

  2. Les promesses sont resolved by a value ;

  3. Les promesses sont rejetées par des exceptions;

  4. Non cancellable et retourne a single value

  5. Une promesse expose une fonction (then)

    -en retourne une nouvelle promise ;

    -applique à la attachment qui sera exécuté en fonction de l’ state ;

    – les handlers sont guaranteed à exécuter dans l’ order attached ;

Je viens de traiter d’un problème pour lequel Promises était la meilleure solution, et je la partage ici pour quiconque est tombé sur cette question dans le cas où cela serait utile (c’était exactement la réponse que je cherchais plus tôt):

Dans un projet Angular2, j’ai un service qui prend des parameters et renvoie une liste de valeurs pour remplir les menus déroulants d’un formulaire. Lorsque le composant de formulaire s’initialise, je dois appeler le même service plusieurs fois avec différents parameters pour définir un certain nombre de menus déroulants différents. Toutefois, si je mets en queue toutes les variables pour appeler le service, seul le dernier réussit et l’erreur de repos en dehors. L’extraction de service à partir de la firebase database ne peut traiter qu’une demande à la fois.

Le seul moyen de remplir avec succès toutes les variables du menu déroulant était d’appeler le service de manière à empêcher le traitement d’une nouvelle demande jusqu’à la fin de la dernière demande et le mécanisme Promise / .then résolvait bien le problème.

  fetchValueList(listCode): Promise { 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 renvoie une promesse. Le premier appel passe donc le premier listCode et, lorsque la promesse est résolue, la valeur renvoyée se trouve dans la variable data du bloc .then où nous pouvons l’affecter à la variable this.firstValList. Comme la fonction a renvoyé des données, nous soaps que le service est terminé et qu’il est possible d’appeler à nouveau avec le deuxième listCode, la valeur renvoyée se trouve dans la variable de données du bloc suivant et nous l’assignerons à la variable this.secondValList.

Nous pouvons enchaîner autant de fois que nécessaire pour remplir toutes les variables, et sur le dernier bloc de code, nous omettons simplement l’instruction return et le bloc se termine.

Il s’agit d’un cas d’utilisation très spécifique où nous avons un seul service qui doit être appelé plusieurs fois lors de l’initialisation du composant et où le service doit terminer sa récupération et retourner une valeur avant de pouvoir être appelé à nouveau, mais dans ce cas, la méthode Promise / .then était idéale.

Je crois que toutes les autres réponses devraient effacer vos doutes. Néanmoins, je voulais juste append que les observables sont basées sur la functional programming, et je trouve très utile les fonctions qui vont avec, comme la carte, la carte, la réduction, le zip. La cohérence obtenue par le Web, en particulier lorsqu’il dépend des demandes d’API, constitue une amélioration brutale.

Je recommande fortement cette documentation , car c’est la documentation officielle de reactiveX et je la trouve la plus claire.

Si vous voulez entrer dans les observables, je suggérerais ce post 3part: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

Bien que cela soit destiné à RxJava, les concepts sont les mêmes, et ils sont très bien expliqués. Dans la documentation de reactiveX, vous avez les équivalences pour chaque fonction. Vous devez rechercher RxJS.

J’espère que cela aide, juste essayé de consortingbuer ici. 🙂

Observables vs Promesses

Les promesses et les observables , les deux nous fournissent une façon simple de nous aider à lutter contre la nature asynchrone de nos applications. Cependant, il existe des différences importantes entre les deux:

  • Les observables peuvent définir les aspects de configuration et de suppression du comportement asynchrone.
  • Les observables sont annulables.
  • De plus, les observables peuvent être réessayés à l’aide de l’un des opérateurs de relance fournis par l’API, tels que Réessayer et RéessayerWhen. D’autre part, Promises exige que l’appelant ait access à la fonction d’origine qui a renvoyé la promesse afin de pouvoir réessayer.

Les promesses imposent effectivement cette sémantique. Vous pouvez créer une promesse qui 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 à nouveau Promise avec une autre valeur échouera. La promesse est toujours résolue avec la première valeur transmise à la fonction de résolution et ignore les appels ultérieurs:

  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, «émettre») des valeurs multiples. Voici à quoi cela 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 basculé Promise vers Observable, remplacé la fonction de résolution par l’appel observations.next et au lieu de s’inscrire subscribe, qui se comporte de manière très similaire.

Promettre:

  • Fournir une valeur future unique;
  • Pas paresseux;
  • Non annulable

Observable:

  • Émet de multiples valeurs au fil du temps;
  • Paresseux;
  • Annulable
  • Prend en charge les opérateurs de cartographie, de filtrage, de réduction et similaires

Vous pouvez utiliser des promesses au lieu d’observables lorsque vous appelez HTTP dans Angular si vous le souhaitez.

Promesse – Fournir une valeur future unique. Pas paresseux . Non annulable Il rejettera ou résoudra.

Observable – Fournit une valeur future multiple. Paresseux . Annulable Il fournit d’autres méthodes en direct sur carte, filtre, réduit.

Aperçu:

  • Les promesses et les observables nous aident à gérer les opérations asynchrones. Ils peuvent appeler certains rappels lorsque ces opérations asynchrones sont effectuées.
  • Une promesse ne peut gérer qu’un seul événement, les observables sont des stream d’événements au fil du temps
  • Les promesses ne peuvent être annulées une fois en attente
  • Les données observables émettent peuvent transformées à l’aide d’opérateurs

Vous pouvez toujours utiliser une observable pour traiter le comportement asynchrone, car une observable a la fonctionnalité d’une promesse. Cependant, parfois, cette fonctionnalité supplémentaire offerte par Observable n’est pas nécessaire. Ensuite, importer une bibliothèque pour les utiliser serait une surcharge supplémentaire.

Quand utiliser les promesses:

Utilisez les promesses lorsque vous avez une seule opération asynchrone dont 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 du code là où elle est résolue ou rejetée. Si la résolution ou le rejet est appelé, la promesse passe d’un état en attente à un état résolu ou rejeté . Lorsque l’état de la promesse est résolu, la méthode then() est appelée. Lorsque l’état de la promesse est rejeté, la méthode catch() est appelée.

Quand utiliser les observables:

Utilisez les observables quand il y a un stream au fil du temps qu’il faut gérer. Dans l’observable lui-même est spécifié lorsque l’événement suivant s’est produit, lorsqu’une erreur s’est produite ou lorsque l’observable est terminé. Ensuite, nous pouvons nous abonner à cette observable, ce qui l’active et dans cet abonnement, nous pouvons transmettre 3 rappels (ne sont pas toujours obligés de tout passer). Un rappel à exécuter pour réussir, un rappel d’erreur et un rappel pour achèvement. 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’une observable, il nécessite une fonction de rappel qui fournit un observateur en argument. Sur cet observateur, vous pouvez alors appeler onNext , onCompleted , onError . Ensuite, lorsque l’observable est abonné, il appelle les rappels correspondants passés dans l’abonnement.

Il y a beaucoup de réponses sur ce sujet déjà, donc je ne voudrais pas en append une redondante.

Mais pour quelqu’un qui vient de commencer à apprendre l’ observable / angular et se demande lequel utiliser en comparaison avec Promise , je vous recommande de garder tout ce qui est observable et de convertir toutes les promesses existantes dans votre projet en Observable.

Tout simplement parce que le cadre angular lui-même et sa communauté utilisent tous Observable. Il serait donc avantageux d’intégrer des services de framework ou des modules tiers et de tout enchaîner.

Expliquer en référence les appels HTTP angulars pour Api distant: Promises est utilisé pour maintenir l’état des appels asynchrones. l’une des données est obtenue à partir Api à distance et montrer à la vue

et dans Observable provient d’un modèle observable et introduit par Rxjs lorsqu’il vous permet de mettre à jour les données plusieurs fois dans le stream en tant que données observables.