Quelle est la différence entre les promesses et les observables?

1399

Quelle est la différence entre PromiseetObservable dans Angular?

Un exemple sur chacun serait utile pour comprendre les deux cas. Dans quel scénario pouvons-nous utiliser chaque cas?

Rohit
la source
23
Je vous suggère de lire ce post; Angular2 promesse vs observable
erolkaya84
4
en termes plus simples angular-2-training-book.rangle.io/handout/observables/…
Pardeep Jain
3
À tous ceux qui lisent ces questions et réponses - en tant que personne impliquée dans les deux mondes par un mainteneur, un orateur et un utilisateur de longue date PoV, je vous encourage à lire les documents officiels RxJS et la documentation MDN sur les promesses. Personnellement, je trouve les réponses ici entièrement trompeuses et incorrectes et je pense qu'elles sont très nuisibles, bien qu'elles aient de bonnes intentions de la part de personnes essayant d'aider.
Benjamin Gruenbaum
1
Je vous suggère de lire ce document officiel angulaire angular.io/guide/comparing-observables
fgul
Et c'est pourquoi les liens sont considérés comme des réponses inacceptables.
Dave

Réponses:

1551

Promettre

A Promisegère un seul événement lorsqu'une opération asynchrone se termine ou échoue.

Remarque: Il existe des Promisebibliothèques qui prennent en charge l'annulation, mais ES6 Promisene le fait pas jusqu'à présent.

Observable

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

Il Observableest souvent préférable à Promisecar il offre les fonctionnalités de Promiseet plus encore. Avec Observablecela 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.

Observablea également l'avantage Promised'être annulable . Si le résultat d'une demande HTTP à un serveur ou d'une autre opération asynchrone coûteuse n'est plus nécessaire, le Subscriptiond'un Observablepermet d'annuler l'abonnement, tandis qu'un Promiseappel finira par appeler le succès ou l'échec du rappel même lorsque vous n'avez pas besoin de la notification ou le résultat qu'il fournit.

Observable fournit des opérateurs comme map, forEach, reduce, ... semblable à un tableau

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

Günter Zöchbauer
la source
180
Y a-t-il donc une bonne raison d'utiliser Promise au lieu d'Observable dans le cas de rappel unique ou les Observables devraient-ils également être utilisés ici car ils peuvent également fonctionner de cette façon? Fondamentalement, est-ce une bonne pratique de «tout observer» ou est-ce que Promise a toujours sa place?
Josh Werts
75
Si vous souhaitez utiliser le style réactif, utilisez simplement des observables partout. Si vous n'avez que des observables, vous pouvez facilement composer. Si vous les mélangez, ce n'est plus si propre. Si vous ne vous souciez pas du style réactif, vous pouvez utiliser la promesse pour des événements uniques où vous ne vous souciez pas des annulations et des observables pour les flux d'événements.
Günter Zöchbauer
35
@ GünterZöchbauer Hey - Je n'ai aucun argument contre Observables ou la programmation fonctionnelle. Je déclare simplement que je crois que les personnes qui se rendent sur Observables principalement via http dans NG2 n'ont aucune raison réelle d'utiliser les Observables sur Promesses pour passer les appels. Ils ne perdent rien de pratique en utilisant des promesses. Les opérateurs debounce et retry ne sont pas pertinents - vous pouvez rebounce avec ng-debounce et si un appel est censé échouer, il y a généralement un problème avec le code. La seule fois où j'avais besoin de retenter des appels était lors de la requête d'API tiers instables pour HVT.
VSO
92
Mais n'oubliez pas que Promise, avec async/ awaitrend votre code à nouveau plat! Dans la majorité des situations, et dans les projets qui ne traitent pas de fusée, il n'est pas nécessaire d'écrire ces horribles fonctions imbriquées avec des chaînes de méthodes inutilement compliquées. Vous pouvez utiliser async/ awaitaujourd'hui avec des transpilers, comme TypeScriptet écrire du code plat lisible par l'homme sans aucun passe- rxjspartout. Vous aurez probablement encore besoin rxjsparfois dans certaines situations, car il a vraiment beaucoup de choses à offrir.
evilkos
15
Cette réponse est trompeuse, un observable n'est pas comme un flux, c'est comme une fonction qui renvoie un flux .
Benjamin Gruenbaum
336

Les deux Promiseset Observablesnous 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.

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

Merci @Christoph Burgdorf pour cet article génial


Angular utilise Rx.js Observables au lieu de promesses pour traiter avec HTTP.

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

  • Nous ne voulons pas toucher le point de terminaison du serveur chaque fois que l'utilisateur appuie sur une touche, cela devrait l'inonder d'une tempête de HTTPdemandes. Fondamentalement, nous ne voulons le frapper qu'une fois que l'utilisateur a arrêté de taper au lieu de chaque frappe.
  • Ne frappez pas le point de terminaison de recherche avec les mêmes paramètres de requête pour les requêtes suivantes.
  • Traitez les réponses en panne. Lorsque nous avons plusieurs demandes en vol en même temps, nous devons tenir compte des cas où elles reviennent dans un ordre inattendu. Imaginez que nous tapons d'abord ordinateur , arrêt, une demande sort, nous tapons voiture , arrêt, une demande sort. Nous avons maintenant deux demandes en vol. Malheureusement, la demande qui porte les résultats pour l' ordinateur revient après la demande qui porte les résultats pour la voiture .

La démo se composera simplement de deux fichiers: app.tset wikipedia-service.ts. Dans un scénario réel, nous diviserions très probablement les choses plus haut, cependant.


Vous trouverez ci-dessous une 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: 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 Jsonpservice pour faire une GETdemande contre l'API Wikipedia avec un terme de recherche donné. Notez que nous appelons toPromisepour passer d'un Observable<Response>à un Promise<Response>. Finalement, vous vous retrouvez 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 beaucoup de surprise ici non plus. Nous injectons notre WikipediaServiceet exposons sa fonctionnalité via une méthode de recherche au modèle. Le modèle se lie simplement à la saisie et aux appels search(term.value).

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

Voir l'exemple d' implémentation basée sur Promise sur Plunker


Où les observables brillent vraiment

Modifions notre code pour ne pas marteler le point de terminaison à chaque frappe, mais envoyer une demande à la place uniquement lorsque l'utilisateur a arrêté de taper pendant 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 tirer parti de la formControldirective d'Angular . Pour utiliser cette directive, nous devons d'abord importer le ReactiveFormsModuledans 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 lui attribuer le nom "term".

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

Dans notre composant, nous créons une instance de FormControlfrom @angular/formet l'exposons en tant que champ sous le terme de nom sur notre composant.

Dans les coulisses, le terme expose automatiquement une Observable<string>propriété as à valueChangeslaquelle nous pouvons souscrire. Maintenant que nous avons un Observable<string>, surmonter l'entrée utilisateur est aussi simple que d'appeler debounceTime(400)notre Observable. Cela retournera une nouvelle Observable<string>qui n'émettra une nouvelle valeur que si aucune nouvelle valeur n'est venue depuis 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 une perte de ressources d'envoyer une autre demande de terme de recherche pour laquelle notre application affiche déjà les résultats. Tout ce que nous avons à faire pour obtenir le comportement souhaité est d'appeler l' distinctUntilChangedopérateur juste après avoir appelédebounceTime(400)

Voir l'exemple d' implémentation observable sur Plunker

Pour traiter les réponses hors service, veuillez consulter l'article complet http://blog.oughttram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

Pour autant que j'utilise Http dans Angular, je conviens que dans les cas d'utilisation normaux, il n'y a pas beaucoup de différence lors de l'utilisation d'Observable sur Promise. Aucun des avantages n'est vraiment pertinent ici dans la pratique. J'espère que je pourrai voir un cas d'utilisation avancée à l'avenir :)


Apprendre encore plus

trungk18
la source
31
Je n'achète pas complètement 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 celui-ci concerne la gestion des événements du navigateur. Je voudrais savoir quel est l'avantage de l'appliquer lors du traitement des requêtes http asynchrones.
Alex Pollan
1
La décision a-t-elle été accidentelle d'éviter les schémas mixtes?
Alex Pollan
6
@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 décrit dans le lien ci-dessus - bien qu'un peu artificiel - est que si vous appelez plusieurs API et ne vous souciez que de la première réponse, peu importe qui des API que vous avez appelées vous revient en premier, vous pouvez ensuite annuler les demandes aux autres.
nikolasleblanc
2
@nikolasleblanc, je suis presque sûr que vous pouvez utiliser $ q.race () pour cela?
jameslouiz
2
@AlexPollan, L'avantage est qu'un service HTTP basé sur Observable permet d'annuler facilement les requêtes HTTP à mi-vol. La condition de concurrence critique dans la réponse de trungk18 peut être résolue en se désabonnant simplement de l'observable HTTP avant de faire une demande ultérieure. RXJS switchMap peut être utilisé pour les requêtes HTTP déclenchées par un autre observable (par exemple valueChanges). Pour les observables HTTP autonomes, vous pouvez vous désabonner et vous réinscrire manuellement.
Stevethemacguy
236

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 y a encore des différences entre les deux, les promesses sont des valeurs qui se résoudront asynchronouscomme des appels http . D'un autre côté, les observables traitent d'une séquence d' événements asynchrones . Les principales différences entre eux sont répertoriées ci-dessous:

promettre:

  • avoir un pipeline
  • généralement utilisé uniquement avec le retour de données asynchrone
  • pas facile d'annuler

observable:

  • sont annulables
  • sont réessayables par nature, comme les nouvelles tentatives et les nouvelles tentatives
  • diffuser des données dans plusieurs pipelines
  • avoir des opérations de type tableau comme la carte, le filtre, etc.
  • peut être créé à partir d'autres sources comme des événements
  • ce sont des fonctions qui pourraient être souscrites ultérieurement

Aussi, j'ai créé l'image graphique pour vous ci-dessous pour montrer les différences visuellement:

Promesses et Observables image

Alireza
la source
4
promesse "pas facile d'annuler", est-il possible de les annuler?
Pardeep Jain
10
oui, il y a un moyen de les annuler aussi ... certaines personnes utilisent des bibliothèques bluebird ou tierces ... aussi en utilisant la bibliothèque Q dans Angular il y a des façons de l'annuler ... mais comme je l'ai dit pas très pratique
Alireza
Avoir un pipeline a parfois un avantage, ex. dans APP_INITIALIZER, si vous avez plusieurs pipelines, il ne peut jamais se terminer parfois ou se terminer plusieurs fois.
windmaomao
6
l'annulation d'un Promiseest la mauvaise façon de penser à la façon dont les promesses. Il lui Promiseincombe uniquement de gérer le succès ou l'échec d'une manière compatible asynchrone. Si vous souhaitez annuler une demande http, vous annulez la demande, et non la promesse, et le résultat de l'annulation remplit ou rejette la promesse. jsfiddle.net/greggman/ea0yhd4p
gman
2
@gman Exactement. La promesse représente simplement une valeur future . Il ne représente pas l' opération qui génère la valeur . Vous ne pouvez pas annuler une valeur. Vous ne pouvez pas réessayer une valeur. C'est juste une valeur. Il peut ou non être encore présent , et il peut ne jamais exister car une exception s'est produite, mais c'est tout.
Yona Appletree
75

Promesses

  1. Définition: vous aide à exécuter des fonctions de manière asynchrone et à utiliser leurs valeurs de retour (ou exceptions) mais une seule fois lors de leur exécution.
  2. Pas paresseux
  3. Non annulable (il existe des bibliothèques Promise qui prennent en charge l'annulation, mais ES6 Promise ne le fait pas jusqu'à présent). Les deux décisions possibles sont
    • Rejeter
    • Résoudre
  4. Ne peut pas être réessayé (les promesses doivent avoir accès à la fonction d'origine qui a renvoyé la promesse d'avoir une capacité de nouvelle tentative, ce qui est une mauvaise pratique)

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 ) lors de leur exécution.
  2. Par défaut, il est paresseux car il émet des valeurs lorsque le temps avance.
  3. A beaucoup d'opérateurs, ce qui simplifie l'effort de codage.
  4. Un opérateur retry peut être utilisé pour une nouvelle tentative en cas de besoin, même si nous devons recommencer l'observable en fonction de certaines conditions retryWhen peut être utilisé.

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

Aravind
la source
67

Il y a un inconvénient d'Observables manquant dans les réponses. Les promesses permettent d'utiliser les fonctions asynchrones / en attente d'ES7. Avec eux, vous pouvez écrire du code asynchrone comme s'il s'agissait d'un appel de fonction synchrone, vous n'avez donc plus besoin de rappels. La seule possibilité pour Observables de le faire est de les convertir en promesses. Mais lorsque vous les convertissez en promesses, vous ne pouvez à nouveau 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 Rx Observable?

besserwisser
la source
21
Aussi surpris pourquoi personne n'a souligné cet avantage tueur de promesses - simplicité et transparence grâce à async / wait. Je suis passé à Promises juste pour la capacité d'écrire du code plat. La logique métier simple et le code d'interaction de l'interface utilisateur ne devraient pas ressembler à des fusées et être pollués par l'enfer imbriqué d'extensions réactives. De plus, async / wait n'est pas seulement à l'avenir, vous pouvez l'utiliser dans des applications de production publiques utilisant maintenant des transpilers. J'utilise TypeScript 2.3 et c'est génial, comme un vrai langage.
evilkos
Sympa, mais penser de manière réactive et tout cela avec les RxOperators, ce n'est peut-être pas une fonctionnalité de tueur
JorgeTovar
37

Promises et Observables gèrent uniquement l'appel asynchrone.

Voici les différences entre eux:

Observable

  1. Emet plusieurs valeurs sur une période de temps
  2. N'est appelé que lorsque nous sommes abonnés à l'Observable
  3. Peut être annulé en utilisant la méthode unsubscribe ()
  4. Fournit la carte, forEach, filtrer, réduire, réessayer et réessayer

Promettre

  1. N'émet qu'une seule valeur à la fois

  2. Appelle les services sans .then et .catch

  3. Ne peut être annulé

  4. Ne fournit aucun opérateur

sudheer nunna
la source
2
Qu'entendez-vous exactement par promesse n'émet qu'une seule valeur, tandis que l'observable en émet plusieurs
Abel
2
Une promesse n'émet pas du tout de valeur - une promesse est une valeur dans le temps. Une promesse multidiffuse cette valeur pour plusieurs abonnés - une fois que vous tenez la promesse, vous avez déjà une valeur. Un observable est comme une fonction , y souscrire invoque l'action.
Benjamin Gruenbaum
1
@BenjaminGruenbaum Je n'ai toujours pas obtenu la moyenne de plusieurs abonnés, pouvez-vous s'il vous plaît fournir un lien ou un exemple. Merci
Deepak Patidar
2
observable1.subscribe (subscriber1), observable1.subscribe (subscriber2) - ceci appelle la fonction plusieurs fois.
Benjamin Gruenbaum
2
Veuillez modifier votre message et afficher le texte réel au lieu de captures d'écran. D'autres ne peuvent pas copier et coller à partir de vos images et ne peuvent pas non plus vous aider à corriger les nombreuses erreurs de grammaire. Voir ici pour plus de détails. Je vous remercie.
Pang
26

Même si cette réponse est en retard, j'ai résumé les différences ci-dessous,

Observable:

  1. Observable est juste un functionqui prend an observeret retourne un function Observer: an object with next, error.
  2. L'observateur permet à subscribe/unsubscribeson flux de données, d'émettre la valeur suivante à l'observateur, à notifyl'observateur errorset à informer l'observateur de lastream completion
  3. Observer fournit un function to handle next value, les erreurs et la fin du flux (événements ui, réponses http, données avec sockets Web).
  4. Fonctionne avec au multiple valuesfil du temps
  5. Il est cancel-able/retry-ableet prend en charge les opérateurs tels que map,filter,reduceetc.
  6. La création d'un Observable peut être - Observable.create()- renvoie Observable qui peut invoquer des méthodes - 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()- retourne une séquence d'entiers dans la plage spécifiée

Promesse :

  1. Une promesse représente une tâche qui se terminera à l'avenir;

  2. Les promesses deviennent resolved by a value;

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

  4. Pas cancellableet ça revienta single value

  5. Une promesse expose une fonction (then)

    -en retourne un nouveau promise;

    -permet à attachmentcelui qui sera exécuté sur la base de state;

    - handlersdoivent guaranteeds'exécuter dans order attached;

Sajeetharan
la source
20

Je viens de traiter un problème où les promesses étaient la meilleure solution, et je la partage ici pour quiconque tombe sur cette question au 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 certains paramètres 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 des paramètres différents pour définir un certain nombre de menus déroulants différents, mais si je mets simplement en file d'attente toutes les variables pour appeler le service, seule la dernière réussit et l'erreur de reste en dehors. Le service récupérant de la base de données ne pouvait gérer qu'une seule demande à la fois.

Le seul moyen 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'à la fin de la dernière demande, et le mécanisme Promise / .then a résolu le problème correctement.

  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 renvoie 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 du bloc .then où nous pouvons l'affecter à la variable this.firstValList. Comme la fonction a renvoyé des données, nous savons que le service est terminé et qu'il est sûr d'appeler à nouveau avec le deuxième listCode, la valeur de retour est dans la variable de données dans le bloc .then suivant et nous l'affectons à la variable this.secondValList.

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 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 renvoyer une valeur avant de pouvoir être appelé à nouveau, mais dans ce cas, la méthode Promise / .then était idéale.

Stephen R. Smith
la source
3
C'est certainement aussi possible avec des observables (d'ordre supérieur). Vous pouvez par exemple utiliser scan()pour construire un flux d'observables séquentiels. Cependant, votre approche est peut-être plus explicite et plus facile à comprendre.
lex82
1
Vous pouvez remplacer "alors" par "switchMap" et faire exactement la même chose avec des observables.
Dr C. Hilarius,
1
Le problème avec switchMap, si je comprends bien, est qu'il va démarrer toutes les requêtes en parallèle et attendre qu'elles reviennent toutes, puis retourner les valeurs à la fonction appelante alors que dans ma situation, j'ai un seul serveur que je ne peux pas appeler plusieurs fois en parallèle (car le serveur supprimera les demandes inachevées lorsque de nouvelles arrivent), j'ai donc dû m'assurer que chaque appel au service de base de données était terminé avant de commencer un nouvel appel, et la promesse / semblait alors être la meilleure et peut-être le seul moyen de résoudre ce problème.
Stephen R. Smith
1
Pourquoi n'avez-vous pas utilisé mergeMap chaîné? Pour autant que j'ai compris votre code, celui-ci est assez simple et fait le travail aussi bien que votre exemple. @ StephenR.Smith
Ore
1
@Ore Pouvez-vous ajouter un exemple de code qui résout le même problème qu'une autre réponse? Ce serait une bonne référence et pourrait être une bonne occasion de refactoring à l'avenir. L'exigence est que, quel que soit le code ne pouvant pas appeler le service backend en parallèle, il doit appeler, attendre la valeur de retour et appeler à nouveau.
Stephen R. Smith
20

Je pense que toutes les autres réponses devraient dissiper vos doutes. Néanmoins, je voulais juste ajouter que les observables sont basés sur une programmation fonctionnelle, et je trouve très utiles les fonctions qui l'accompagnent comme map, flatmap, réduire, zip. La cohérence que le Web atteint, en particulier lorsqu'il dépend des demandes d'API, est une amélioration brutale.

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

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

Bien que cela soit destiné à RxJava, les concepts sont les mêmes, et c'est vraiment bien expliqué. Dans la documentation reactiveX, vous avez les équivalences pour chaque fonction. Vous devez rechercher RxJS.

Marc Pérez
la source
18

Promettre:

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

Observable:

  • Emet plusieurs valeurs au fil du temps;
  • Paresseux;
  • Annulable;
  • Prend en charge les opérateurs de carte, de filtre, de réduction et similaires

Vous pouvez utiliser des promesses au lieu d'observables lorsque vous appelez HTTP en angulaire si vous le souhaitez.

Iosua Sipos
la source
16

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 terminées.
  • Une promesse ne peut gérer qu'un seul événement, les observables concernent des flux d'événements dans le temps
  • Les promesses ne peuvent pas être annulées une fois qu'elles sont en attente
  • Les données observables émises peuvent être transformées à l'aide d'opérateurs

Vous pouvez toujours utiliser un observable pour gérer le comportement asynchrone car un observable a toutes les fonctionnalités qu'une promesse offre (+ extra). Cependant, parfois, cette fonctionnalité supplémentaire qu'offre Observables n'est pas nécessaire. Il serait alors un surcoût supplémentaire d'importer une bibliothèque pour qu'elle puisse les utiliser.

Quand utiliser Promises:

Utilisez des 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 où elle se résout ou rejette. 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 promis est résolu, la then()méthode est appelée. Lorsque l'état promis est rejeté, la catch()méthode est appelée.

Quand utiliser Observables:

Utilisez Observables quand il y a un flux (de données) dans le temps que vous devez gérer. Un flux est une séquence d'éléments de données qui sont rendus disponibles au fil du temps . Voici des exemples de flux:

  1. Événements utilisateur, par exemple des événements de clics ou de touches. L'utilisateur génère des événements (données) au fil du temps.
  2. Websockets, une fois que le client a établi une connexion WebSocket avec le serveur, il envoie des données au fil du temps.

Dans l'Observable lui-même est spécifié lorsque l' événement suivant s'est produit, lorsqu'une erreur se produit ou lorsque l'Observable est terminé . Ensuite, nous pouvons souscrire à cet observable, qui l'active et dans cet abonnement, nous pouvons passer en 3 rappels (ne pas toujours avoir à passer en tout). Un rappel à exécuter pour réussir, un rappel pour erreur et un rappel pour terminer. 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 appeler onNext, onCompleted, onError. Ensuite, lorsque l'Observable est abonné, il appellera les rappels correspondants passés dans l'abonnement.

Willem van der Veen
la source
9

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

Observable - Fournit une valeur future multiple. Paresseux . Annulable. Il fournit d'autres méthodes pour cartographier en direct, filtrer, réduire.

Gajender Singh
la source
8

Promesse vs similitude observable en premier

  1. Les deux sont utilisés pour gérer le code asynchrone.
  2. Veuillez rechercher un exemple de promesse. Le constructeur de promesse passe une fonction de référence de résolution qui sera appelée lorsqu'elle sera appelée avec une certaine valeur à la fin d'une tâche asynchrone.

const promise = new Promise(resolve => {
  setTimeout(() => {
    resolve("Hello from a Promise!");
  }, 2000);
});

promise.then(value => console.log(value));

  1. Exemple observable maintenant. Ici aussi, nous passons une fonction à observable, un observateur pour gérer la tâche asynchrone. Contrairement à résoudre dans la promesse, il a la méthode suivante et s'abonne à la place.

  2. Les deux gèrent donc les tâches asynchrones. Voyons maintenant la différence.


const observable = new Observable(observer => {
  setTimeout(() => {
    observer.next('Hello from a Observable!');
  }, 2000);
});

observable.subscribe(value => console.log(value));

Promesse vs différence observable

Promettre

  1. Il résout ou rejette une seule valeur et peut gérer une tâche asynchrone à une seule valeur à la fois.
  2. Une promesse une fois résolue la valeur asynchrone qu'elle remplit, ne peut plus être utilisée.
  3. Non annulable
  4. Aucun support rxjs pour les opérateurs.

Observable

  1. possibilité d'émettre plusieurs valeurs asynchrones.
  2. Utilisé pour gérer le flux d'événements ou de valeurs. Considérez que vous avez un tableau de nombreuses tâches ou valeurs, et que vous voulez que chaque fois que la valeur est insérée, elle doit être gérée automatiquement. Chaque fois que vous insérez une valeur dans ce tableau, tous ses abonnés recevront automatiquement la dernière valeur.
  3. Les observables sont utiles pour observer les changements d'entrée, les intervalles répétés, les valeurs de diffusion vers tous les composants enfants, les notifications push de socket Web, etc.
  4. Peut être annulé à tout moment à l'aide de la méthode de désabonnement.
  5. Une dernière bonne partie de cette promesse est le support des opérateurs rxjs. Vous avez de nombreux opérateurs de tuyaux principalement mapper, filtrer, switchMap, combineLatest, etc. pour transformer les données observables avant de vous abonner.

entrez la description de l'image ici


ramesh sharma
la source
6

Les promesses et les observables nous aident à gérer les opérations asynchrones. Ils peuvent appeler certains rappels lorsque ces opérations asynchrones sont terminées.

Angular utilise Observables qui est de RxJS au lieu de promesses pour traiter avec HTTP

Below are some important differences in promises & Observables.

différence entre les promesses et les observables

Srikrushna
la source
1
Les données du tableau semblent incorrectes, le titre devrait être échangé
Derrick.X
1
Veuillez modifier votre message et afficher le contenu réel sous forme de texte au lieu de captures d'écran. D'autres ne peuvent pas copier et coller à partir de vos images. Voir ici pour plus de détails. Je vous remercie.
Pang
6

Une promesse émet un seul événement lorsqu'une activité asynchrone se termine ou échoue.

Un observable est comme un flux (dans de nombreuses langues) et permet de passer au moins zéro ou plusieurs événements où le rappel est requis pour chaque événement.

Fréquemment observable est préféré à Promise car il donne les points forts de Promise et plus encore. Avec Observable, peu importe si vous devez gérer 0, 1 ou divers événements. Vous pouvez utiliser l'API similaire pour chaque cas.

Promesse: la promesse émet une seule valeur

Par exemple:

const numberPromise = new Promise((resolve) => {
    resolve(5);
    resolve(10);
});

numberPromise.then(value => console.log(value));
// still prints only 5

Observable: émet plusieurs valeurs sur une période de temps

Par exemple:

  const numberObservable = new Observable((observer) => {
        observer.next(5);
        observer.next(10);
    });

numberObservable.subscribe(value => console.log(value));
// prints 5 and 10

nous pouvons penser à un observable comme un flux qui émet plusieurs valeurs sur une période de temps et la même fonction de rappel est appelée pour chaque élément émis, donc avec un observable nous pouvons utiliser la même API pour gérer les données asynchrones. si ces données sont transmises en tant que valeur unique ou valeurs multiples sur une certaine période de temps.

Promettre:

  • Une promesse n'est pas paresseuse
  • Une promesse ne peut pas être annulée

Observable:

  • Observable est paresseux. L '"observable" est lent. Il n'est appelé que lorsque nous y sommes abonnés.
  • Un observable peut être annulé en utilisant la méthode unsubscribe ()
  • Un ajout Observable fournit de nombreux opérateurs puissants comme la carte, foreach, filtrer, réduire, réessayer, réessayer quand etc.

Promesses angulaires vs observables

Déc
la source
5

Promise émet une seule valeur tandis que Observable émet plusieurs valeurs. Ainsi, lors de la gestion d'une demande HTTP, Promise peut gérer une seule réponse pour la même demande, mais qu'en est-il s'il existe plusieurs réponses à la même demande, nous devons utiliser Observable. Oui, Observable peut gérer plusieurs réponses pour la même demande.

Promettre

const promise = new Promise((data) =>
{ data(1);
  data(2);
  data(3); })
.then(element => console.log(‘Promise ‘ + element));

Production

Promise 1

Observable

const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));

Production

Observable 1
Observable 2
Observable 3
yogesh waghmare
la source
3

Voici quelques différences importantes dans les promesses et les observables.

Promettre

  • N'émet qu'une seule valeur
  • Non annulable
  • Non partageable
  • Toujours asynchrone

Observable

  • Emet plusieurs valeurs
  • S'exécute uniquement lorsqu'il est appelé ou que quelqu'un s'abonne
  • Peut être annulable
  • Peut être partagé et abonné cette valeur partagée par plusieurs abonnés. Et tous les abonnés s'exécuteront à un moment donné.
  • éventuellement asynchrone

Pour une meilleure compréhension, consultez le https://stackblitz.com/edit/observable-vs-promises

Bikram
la source
3

Je vois beaucoup de gens utiliser l'argument selon lequel les observables sont "annulables" mais il est plutôt trivial de rendre Promise "annulable"

function cancellablePromise(body) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res; reject = rej;
    body(resolve, reject)
  })
  promise.resolve = resolve;
  promise.reject = reject;
  return promise
}

// Example 1: Reject a promise prematurely
const p1 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('10', 100))
})

p1.then(value => alert(value)).catch(err => console.error(err))
p1.reject(new Error('denied')) // expect an error in the console

// Example: Resolve a promise prematurely
const p2 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('blop'), 100)
})

p2.then(value => alert(value)).catch(err => console.error(err))
p2.resolve(200) // expect an alert with 200

Batiste Bieler
la source
2

Réponse courte :

Observable est meilleur , il a toutes les fonctionnalités Promises et des fonctionnalités supplémentaires.


Longue réponse:

Promesses:

  • Utilisation unique "Renvoyer les données une fois"
  • Aucune annulation
  • Un auditeur
  • Pas de prise en charge d'un écouteur

Observable:

  • Renvoyer des données plusieurs fois lorsque les données changent
  • Support annuler
  • Prise de support
  • Soutenez de nombreux écouteurs et informez-les lorsque les données changent
  • Soutenir la carte, filtrer, réduire
Amr Ibrahim
la source
Je ne pense pas que vous puissiez dire que les observables sont objectivement meilleurs. Il y a un certain nombre d'inconvénients aux observables notés dans les différentes réponses ici. Ceux qui me paraissent être la complexité d'Observable, et qu'ils ne fonctionnent pas directement avec wait / async. Personnellement, je les trouve très difficiles à travailler car vous ne pouvez pas déterminer le comportement d'un observable lorsque vous l'utilisez - vous devez regarder le code qui l'a généré. Alors qu'avec une promesse, vous savez exactement comment ils fonctionnent, toujours. Par exemple, l'abonnement à un Observable a parfois des effets secondaires (par exemple une requête http), mais parfois non.
Yona Appletree
Pour angulaire, cela dépend de votre cas. dans la plupart des cas, nous travaillerons avec des services et certaines données qui affecteront différents endroits, prises, annulation, carte, filtrer et réduire. il sera donc préférable sur ces cas que les promesses ne les soutiennent pas. encore une fois, cela dépend de votre cas
Amr Ibrahim
2

Bien que la réponse acceptée soit bonne en général, je ne pense pas qu'elle souligne que lorsque vous traitez avec des composants angulaires, vous voulez presque toujours utiliser un observable car il prend en charge l'annulation. Les promesses ne peuvent pas être annulées et seront résolues même si votre composant est détruit. Angular a tendance à pardonner jusqu'à ce qu'il ne le soit pas.

Par exemple, toute détection de modification manuelle sur un composant détruit provoquera une exception:

ngOnInit() {
  // promise api
  this.service.getData().then(d => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });

  // observable api
  this.service.getData().pipe(takeUntil(this.unsubscribe)).subscribe((d) => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });
}

Si votre composant est détruit avant la résolution de la promesse, vous obtiendrez une attempt to use destroyed viewerreur lorsque la promesse sera résolue.

Alternativement, si vous utilisez des observables avec le modèle takeUntil , dès que votre composant est détruit, l'abonnement sera annulé.

C'est un peu un exemple artificiel, mais l'exécution de code pour un composant qui est détruit va probablement conduire à des bugs. Sauf si vous voulez réellement le faire pour une raison quelconque: p

shusson
la source
2

Quelque chose que j'ai rencontré qui n'était pas apparent lors de la première lecture du tutoriel et des documents était l'idée de la multidiffusion.

Assurez-vous que par défaut, plusieurs abonnements déclencheront plusieurs exécutions dans un observable. Plusieurs abonnements à un seul appel HTTP Observable déclencheront plusieurs appels HTTP identiques, sauf si vous.share() (activez la multidiffusion).

Une promesse vous oblige à traiter une chose à la fois, à déballer ses données, à gérer les exceptions, à prendre en charge les langues pour des choses sympas comme async / wait, et est assez simple sinon.

Un observable a beaucoup de cloches et de sifflets, mais vous devez comprendre le pouvoir avec lequel vous travaillez ou il peut être mal utilisé.

rpgFANATIC
la source
2

Promettre:

An Async Event Handler - L'objet Promise représente l'achèvement (ou l'échec) éventuel d'une opération asynchrone et sa valeur résultante.

Syntaxe: new Promise (exécuteur);

Par exemple:

var promise_eg = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

promise_eg.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

console.log(promise_eg);

entrez la description de l'image ici

À propos de Promise: il possède un pipeline, il ne renverra donc de valeurs qu'une fois lors de son appel. son gestionnaire à sens unique donc une fois appelé, vous ne pourrez peut-être pas annuler. syntaxe utile que vous pouvez jouer, quand () et puis ()

Observables:

Les observables sont des collections paresseuses de plusieurs valeurs au fil du temps. c'est vraiment une excellente approche pour les opérations asynchrones. cela peut être fait avec rxjs qui a un support multiplateforme peut utiliser avec angular / react etc.

son acte comme stream liner. peut être multi-pipeline. donc une fois défini, vous pouvez vous abonner pour obtenir des résultats de retour dans de nombreux endroits.

Syntaxe: import * as Rx from "@reactivex/rxjs"; à init:

Rx.Observable.fromEvent(button, "click"),
Rx.Subject()

etc

s'inscrire: RxLogger.getInstance();

Par exemple:

import { range } from 'rxjs';
import { map, filter } from 'rxjs/operators';

range(1, 200).pipe(
  filter(x => x % 2 === 1),
  map(x => x + x)
).subscribe(x => console.log(x));

comme il prend en charge plusieurs pipelines, vous pouvez vous abonner à différents endroits, entrez la description de l'image ici il a beaucoup de possibilités que de promesses.

Utilisation: il a plus de possibilités commemap, filter, pipe, map, concatMap etc

Mohideen bin Mohammed
la source
2

La différence fondamentale entre observable et promesse est:

entrez la description de l'image ici

Chirag
la source
2
Veuillez modifier votre message et afficher le contenu réel sous forme de texte au lieu de captures d'écran. D'autres ne peuvent pas copier et coller à partir de vos images. Voir ici pour plus de détails. Je vous remercie.
Pang
1

Les observables sont souvent comparés aux promesses. Voici quelques différences clés:

Les observables sont déclaratifs; le calcul ne démarre pas avant l'abonnement. Les promesses s'exécutent immédiatement à la création. Cela rend les observables utiles pour définir des recettes qui peuvent être exécutées chaque fois que vous avez besoin du résultat.

Les observables fournissent de nombreuses valeurs. Les promesses en fournissent un. Cela rend les observables utiles pour obtenir plusieurs valeurs au fil du temps.

Les observables différencient le chaînage et l'abonnement. Les promesses n'ont que des clauses .then (). Cela rend les observables utiles pour créer des recettes de transformation complexes à utiliser par d'autres parties du système, sans provoquer l'exécution du travail.

Observables subscribe () est responsable du traitement des erreurs. Les promesses poussent les erreurs vers les promesses de l'enfant. Cela rend les observables utiles pour la gestion centralisée et prévisible des erreurs.

C'est la différence la plus simple que vous puissiez trouver sur les documents ANGULAR.IO. la réponse au repos est donnée par la plupart est correcte à sa place

ankita kumari
la source
1
  1. Les promesses sont focalisées uniquement pour des valeurs uniques ou résolues, les observables sont des flux de données.

  2. Les observables peuvent être annulés mais les promesses ne peuvent pas être annulées.

Le moins connu, du moins pour moi, c'est

  1. Les promesses sont toujours de nature asynchrone, mais les observables peuvent être à la fois synchrones et asynchrones.
Vignesh
la source
0
  1. une promesse est impatiente, tandis qu'un observable est paresseux,
  2. une promesse est toujours asynchrone, tandis qu'une observable peut être synchrone ou asynchrone,
  3. une promesse peut fournir une seule valeur, tandis qu'une observable est un
    flux de valeurs (de 0 à plusieurs valeurs),
  4. vous pouvez appliquer des opérateurs RxJS à un observable pour obtenir un nouveau flux personnalisé.
yogesh waghmare
la source
-1

Observables et Promises nous aident à travailler avec les fonctionnalités asynchrones en JavaScript / tapuscrit. Ils sont très similaires dans de nombreux cas, cependant, il existe encore des différences entre eux.

entrez la description de l'image ici

FAISAL
la source
1
Veuillez modifier votre message et afficher le texte réel au lieu de captures d'écran. D'autres ne peuvent pas copier et coller à partir de vos images. Voir ici pour plus de détails. Je vous remercie.
Pang
Sauf que ce n'est pas du code mais des informations simples, donc je pense que c'est correct de le poster comme une image
Alator
1
arrêter de copier-coller à partir des vidéos YouTube de Kudvenkat. Downvote de moi! :)
Pratik
-2

Il y a déjà beaucoup de réponses sur ce sujet, donc je n'ajouterais pas de réponse redondante.

Mais à quelqu'un qui vient de commencer à apprendre Observable / Angular et se demande lequel utiliser comparer avec Promise , je vous recommande de garder tout Observable et de convertir toutes les promesses existantes de votre projet en Observable.

Tout simplement parce que le framework Angular lui-même et sa communauté utilisent tous Observable. Il serait donc avantageux lorsque vous intégrez des services-cadres ou des modules tiers et que vous enchaînez tout ensemble.


Bien que j'apprécie tous les downvotes, mais j'insiste toujours sur mon opinion ci-dessus, à moins que quelqu'un ne fasse un commentaire approprié pour répertorier quelques scénarios qui pourraient encore être utiles dans votre projet Angular pour utiliser Promises over Observables.

Bien sûr, aucune opinion n'est 100% correcte dans tous les cas, mais au moins je pense que 98% du temps pour les projets commerciaux réguliers mis en œuvre dans le 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 loisir simple, vous réaliserez bientôt presque tous les composants avec lesquels vous interagissez dans Angular, et la plupart des frameworks tiers Angular friendly utilisent Observables, puis vous a fini par convertir constamment votre Promesse en Observable afin de communiquer avec eux.

Ces composants incluent, mais sans s'y limiter: HttpClient, Form builder, Angular material modules / dialogs, Ngrx store / effects et ngx-bootstrap.

En fait, la seule promesse de l'écosystème angulaire que j'ai traitée au cours des 2 dernières années est APP_INITIALIZER.

Xinan
la source