Qual'è la differenza tra Promises e Observables?


1398

Qual'è la differenza tra Promisee Observablein Angular?

Un esempio su ciascuno sarebbe utile per comprendere entrambi i casi. In quale scenario possiamo usare ogni caso?


23
Ti consiglio di leggere questo post; Angular2 promessa vs osservabile
erolkaya84,


3
A chiunque legga queste domande e risposte - in quanto persona coinvolta in entrambi i mondi da un manutentore, relatore e utente di lunga data PoV, vi incoraggio a leggere i documenti ufficiali di RxJS e la documentazione MDN sulle promesse. Personalmente trovo le risposte del tutto fuorvianti e errate e credo che siano, sebbene con buone intenzioni da parte di persone che cercano di aiutare, molto dannose.
Benjamin Gruenbaum,

1
Ti suggerirei di leggere questo documento ufficiale angolare angular.io/guide/comparing-observables
fgul

Ed è per questo che i collegamenti sono considerati inaccettabili come risposte.
Dave,

Risposte:


1551

Promettere

A Promisegestisce un singolo evento quando un'operazione asincrona viene completata o ha esito negativo.

Nota: ci sono Promiselibrerie là fuori che supportano la cancellazione, ma ES6 Promisenon è così lontano.

Osservabile

An Observableè come un Stream(in molte lingue) e consente di passare zero o più eventi in cui viene chiamato il callback per ogni evento.

Spesso Observableè preferito Promiseperché fornisce le funzionalità di Promisee altro ancora. Con Observableesso non importa se si desidera gestire 0, 1 o più eventi. Puoi utilizzare la stessa API in ogni caso.

Observableha anche il vantaggio Promisedi essere cancellabile . Se il risultato di una richiesta HTTP a un server o qualche altra costosa operazione asincrona non è più necessario, Subscriptionof of Observableconsente di annullare la sottoscrizione, mentre a Promisealla fine chiamerà il successo o il callback non riuscito anche quando non è necessaria la notifica o il risultato che fornisce più.

Osservabile fornisce operatori come map, forEach, reduce, ... simile a una matrice

Ci sono anche potenti operatori come retry(), o replay(), ... che sono spesso abbastanza utili.


180
Quindi c'è un buon motivo per usare Promise invece di Observable nel singolo caso di callback o dovrebbero essere usati anche lì poiché possono funzionare anche in questo modo? Fondamentalmente, è buona prassi "Osservare tutte le cose" o Promise ha ancora il suo posto?
Josh Werts,

75
Se vuoi usare lo stile reattivo, usa osservabili ovunque. Se hai solo osservabili, puoi facilmente scrivere. Se li mescoli non è più così pulito. Se non ti interessa lo stile reattivo, puoi usare la promessa per singoli eventi in cui non ti importa di cancellabile e osservabile per flussi di eventi.
Günter Zöchbauer,

35
@ GünterZöchbauer Ehi, non ho argomenti contro gli osservabili o la programmazione funzionale. Sto semplicemente affermando che credo che le persone che si imbattono in osservabili principalmente via http in NG2 non abbiano alcun motivo reale per usare gli osservabili oltre le promesse per effettuare le chiamate. Non perdono nulla di pratico usando le promesse. Gli operatori di debounce e tentativi sono irrilevanti: è possibile debounce con ng-debounce e se si prevede che una chiamata fallisca, in genere si verifica un problema con il codice. L'unica volta in cui ho dovuto lavorare con i tentativi di chiamata è stato durante la query di API di terze parti instabili per HVT.
VSO,

92
Ma per favore non dimenticarlo Promise, insieme a async/ awaitrende di nuovo il tuo codice piatto! Nella maggior parte delle situazioni e in progetti che non trattano di scienza missilistica, non è necessario scrivere quelle orribili funzioni annidate con catene di metodi inutilmente complicate. Puoi usare async/ awaitoggi con i transpiler, come TypeScript, e scrivere un vero codice flat leggibile dall'uomo senza alcuna piastra della caldaia rxjs. Probabilmente avrai ancora bisogno a rxjsvolte in determinate situazioni, perché ha davvero molte cose da offrire.
evilkos,

15
Questa risposta è fuorviante, un osservabile non è come un flusso, è come una funzione che restituisce un flusso .
Benjamin Gruenbaum,

335

Entrambi Promisese Observablesci forniscono astrazioni che ci aiutano a gestire la natura asincrona delle nostre applicazioni. La differenza tra loro è stata chiaramente evidenziata da @ Günter e @Relu.

Poiché uno snippet di codice vale più di mille parole, passa attraverso l'esempio seguente per capirle più facilmente.

Grazie @Christoph Burgdorf per il fantastico articolo


Angular utilizza Rx.js Observables invece di promesse per gestire HTTP.

Supponiamo che tu stia creando una funzione di ricerca che dovrebbe mostrarti immediatamente i risultati durante la digitazione. Sembra familiare ma ci sono molte sfide che derivano da questo compito.

  • Non vogliamo colpire l'endpoint del server ogni volta che l'utente preme un tasto, dovrebbe inondarli di una tempesta di HTTPrichieste. Fondamentalmente, vogliamo colpirlo solo quando l'utente ha smesso di digitare invece che ad ogni pressione di un tasto.
  • Non colpire l'endpoint di ricerca con gli stessi parametri di query per le richieste successive.
  • Gestisci le risposte fuori ordine. Quando abbiamo più richieste in volo contemporaneamente, dobbiamo tenere conto dei casi in cui ritornano in un ordine imprevisto. Immagina di digitare prima il computer , fermarsi, una richiesta esce, digitare l' auto , fermarsi, una richiesta esce. Ora abbiamo due richieste in volo. Sfortunatamente, la richiesta che porta i risultati per computer ritorna dopo la richiesta che porta i risultati per auto .

La demo consisterà semplicemente in due file: app.tse wikipedia-service.ts. In uno scenario del mondo reale, molto probabilmente divideremmo le cose più in alto.


Di seguito è riportata un'implementazione basata su Promise che non gestisce nessuno dei casi limite descritti.

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]);
  }
}

Stiamo iniettando il Jsonpservizio per effettuare una GETrichiesta all'API di Wikipedia con un determinato termine di ricerca. Si noti che chiamiamo toPromiseper passare da Observable<Response>a a Promise<Response>. Alla fine si finisce con un Promise<Array<string>>come tipo di ritorno del nostro metodo di ricerca.

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);
  }
}

Anche qui non c'è molta sorpresa. Iniettiamo la nostra WikipediaServiceed esponiamo la sua funzionalità tramite un metodo di ricerca al modello. Il modello si lega semplicemente al keyup e alle chiamate search(term.value).

Scartiamo il risultato della Promessa che il metodo di ricerca di WikipediaService ritorna e lo espone come un semplice array di stringhe al modello in modo da poterlo *ngForscorrere e costruire un elenco per noi.

Vedi l'esempio dell'implementazione basata su Promise su Plunker


Dove gli osservabili brillano davvero

Cambiamo il nostro codice per non martellare l'endpoint con ogni sequenza di tasti, ma inviamo invece una richiesta solo quando l'utente ha smesso di digitare per 400 ms

Per svelare tali superpoteri dobbiamo prima ottenere un termine Observable<string>che contenga il termine di ricerca digitato dall'utente. Invece di associarlo manualmente all'evento keyup, possiamo trarre vantaggio dalla formControldirettiva di Angular . Per utilizzare questa direttiva, dobbiamo prima importare ReactiveFormsModulenel nostro modulo applicativo.

app.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { JsonpModule } from '@angular/http';
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [BrowserModule, JsonpModule, ReactiveFormsModule]
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

Una volta importato, possiamo usare formControl dal nostro modello e impostarlo sul nome "termine".

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

Nel nostro componente, creiamo un'istanza di FormControlfrom @angular/forme la esponiamo come un campo sotto il termine del nome sul nostro componente.

Dietro le quinte, il termine espone automaticamente una Observable<string>proprietà come a valueChangescui possiamo abbonarci. Ora che abbiamo un Observable<string>, superare l'input dell'utente è facile come chiamare debounceTime(400)il nostro Observable. Ciò restituirà un nuovo Observable<string>che emetterà un nuovo valore solo quando non ci sono stati nuovi valori per 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));
  }
}

Sarebbe uno spreco di risorse inviare un'altra richiesta per un termine di ricerca per cui la nostra app mostra già i risultati. Tutto quello che dobbiamo fare per raggiungere il comportamento desiderato è chiamare l' distinctUntilChangedoperatore subito dopo aver chiamatodebounceTime(400)

Vedi l'esempio di implementazione osservabile su Plunker

Per gestire le risposte fuori ordine, consulta l'articolo completo http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

Per quanto sto usando Http in angolare, sono d'accordo che nei casi d'uso normali non c'è molta differenza quando si usa Observable over Promise. Nessuno dei vantaggi è davvero rilevante qui in pratica. Spero di vedere qualche caso d'uso avanzato in futuro :)


Per saperne di più


31
Non compro completamente la decisione di trasformare il servizio Http in base osservabile. Ogni spiegazione che ascolto si basa sullo stesso esempio: la ricerca per termine. Ma quello riguarda la gestione degli eventi del browser. Mi piacerebbe sapere qual è il vantaggio nell'applicarlo quando si tratta di richieste http asincrone.
Alex Pollan,

1
La decisione è stata accidentale di evitare schemi contrastanti?
Alex Pollan,

6
@AlexPollan, in realtà c'è una buona spiegazione per i vantaggi del servizio http che restituisce un osservabile su questo podcast con Ben Lesh: devchat.tv/js-jabber/… . In definitiva, il vantaggio principale è che puoi cancellare un osservabile, e un caso d'uso per questo descritto nel link sopra - mentre un po 'forzato - è che se chiami a più API e ti preoccupi solo della prima risposta, non importa quale delle API che hai chiamato ti viene restituito prima, puoi quindi annullare le richieste agli altri.
nikolasleblanc,

2
@nikolasleblanc, sono abbastanza sicuro di poter usare $ q.race () per questo?
Jameslouiz,

2
@AlexPollan, Il vantaggio è che un servizio HTTP basato su Observable semplifica l'annullamento delle richieste HTTP a metà volo. Le condizioni di competizione nella risposta di trungk18 possono essere risolte semplicemente cancellando l'osservazione HTTP prima di effettuare una richiesta successiva. RXJS switchMap può essere utilizzato per richieste HTTP attivate da un altro osservabile (ad es. ValueChanges). Per gli osservabili HTTP autonomi, puoi annullare l'iscrizione e iscriverti di nuovo manualmente.
Stevethemacguy,

236

Sia Promises che Observables ci aiuteranno a lavorare con le funzionalità asincrone in JavaScript. Sono molto simili in molti casi, tuttavia ci sono ancora alcune differenze tra i due, le promesse sono valori che si risolveranno in asynchronousmodi come le chiamate http . D'altra parte, gli osservabili hanno a che fare con una sequenza di eventi asincroni . Le principali differenze tra loro sono elencate di seguito:

promettere:

  • avendo una pipeline
  • di solito utilizzare solo con il ritorno dei dati asincrono
  • non facile da cancellare

osservabile:

  • sono cancellabili
  • sono ritraibili per natura come riprovare e riprovare
  • flusso di dati in più pipeline
  • avere operazioni simili a array come mappa, filtro ecc
  • può essere creato da altre fonti come eventi
  • sono funzioni che potrebbero essere sottoscritte in seguito

Inoltre, ho creato l'immagine grafica per te di seguito per mostrare visivamente le differenze:

Immagine di promesse e osservabili


4
promettere "non facile da cancellare", è possibile cancellarli?
Pardeep Jain,

10
sì, c'è un modo per cancellarli anche ... alcune persone usano bluebird o librerie di terze parti ... anche usando Q library in Angular ci sono modi per annullarlo ... ma come ho detto non molto utile
Alireza

Avere una pipeline a volte ha un vantaggio, ad es. in APP_INITIALIZER, se disponi di più pipeline, non può mai finire a volte o finire più volte.
windmaomao,

6
l'annullamento di a Promiseè il modo sbagliato di pensare alle promesse. È Promiseresponsabilità solo gestire il successo o il fallimento in modo asincrono compatibile. Se si desidera annullare una richiesta http, si annulla la richiesta, non la promessa, e si ottiene il risultato dell'annullamento o soddisfare o rifiutare la promessa. jsfiddle.net/greggman/ea0yhd4p
gman

2
@gman esattamente. La promessa rappresenta semplicemente un valore futuro . Esso non rappresenta l' operazione che genera il valore . Non è possibile cancellare un valore. Non è possibile riprovare un valore. È solo un valore. Potrebbe essere o non essere ancora presente e potrebbe non esistere mai perché si è verificata un'eccezione, ma il gioco è fatto.
Yona Appletree,

75

promesse

  1. Definizione: consente di eseguire le funzioni in modo asincrono e di utilizzare i valori restituiti (o le eccezioni) ma solo una volta quando vengono eseguite.
  2. Non pigro
  3. Non cancellabile (Esistono librerie Promise che supportano la cancellazione, ma ES6 Promise non è così lontano). Le due possibili decisioni sono
    • Rifiutare
    • Risolvere
  4. Non è possibile riprovare (le promesse dovrebbero avere accesso alla funzione originale che ha restituito la promessa di avere una capacità di nuovo tentativo, che è una cattiva pratica)

osservabili

  1. Definizione: consente di eseguire le funzioni in modo asincrono e di utilizzare i loro valori di ritorno in una sequenza continua ( più volte ) durante l'esecuzione.
  2. Per impostazione predefinita, è Lazy in quanto emette valori quando il tempo avanza.
  3. Ha molti operatori che semplificano lo sforzo di codifica.
  4. È possibile utilizzare un nuovo operatore per riprovare ogni volta che è necessario, anche se è necessario riprovare l'osservabile in base ad alcune condizioni. Riprovare Quando è possibile utilizzare.

    Nota : un elenco di operatori insieme ai loro diagrammi interattivi è disponibile qui su RxMarbles.com


67

C'è un aspetto negativo di Observables mancante nelle risposte. Le promesse consentono di utilizzare le funzioni asincrono / attendono ES7. Con loro puoi scrivere codice asincrono come se fosse una chiamata di funzione sincrona, quindi non hai più bisogno di callback. L'unica possibilità per gli osservabili di farlo è convertirli in promesse. Ma quando li converti in Promises, puoi avere di nuovo un solo valore di ritorno:

async function getData(){
    const data = await observable.first().toPromise();
    //do stuff with 'data' (no callback function needed)
}

Ulteriori letture: come posso `attendere` su un Rx osservabile?


21
Sorpreso anche perché nessuno ha sottolineato questo vantaggio assassino di Promesse: semplicità e trasparenza grazie ad async / wait. Sono passato a Promises solo per la capacità di scrivere codice flat. La semplice logica aziendale e il codice di interazione dell'interfaccia utente non dovrebbero apparire come scienza missilistica ed essere inquinati dall'inferno annidato di estensioni reattive. Inoltre, async / await non è solo in futuro, ma puoi utilizzarlo nelle app di produzione pubblica ora usando i transpiler. Uso TypeScript 2.3 ed è fantastico, come un vero linguaggio.
evilkos,

Bello, ma pensare in modo reattivo e tutto con gli RxOperators forse questa non è una caratteristica killer
JorgeTovar,

37

Promesse e osservabili entrambi gestiscono solo la chiamata asincrona.

Ecco le differenze tra loro:

Osservabile

  1. Emette più valori per un periodo di tempo
  2. Non viene chiamato fino a quando non ci iscriviamo all'Osservabile
  3. Può essere annullato utilizzando il metodo unsubscribe ()
  4. Fornisce la mappa, per Ognuno, filtra, riduce, riprova e riprova quando gli operatori

Promettere

  1. Emette un solo valore alla volta

  2. Chiama i servizi senza .then e .catch

  3. Non può essere cancellato

  4. Non fornisce alcun operatore


2
Cosa intendi esattamente per promessa emette un solo valore, mentre osservabile emette multipli
Abel

2
Una promessa non emette alcun valore: una promessa è un valore nel tempo. Una promessa multicast che apprezza più abbonati: una volta mantenuta la promessa, hai già un valore. Un osservabile è come una funzione , iscrivendosi ad esso invoca l'azione.
Benjamin Gruenbaum,

1
@BenjaminGruenbaum Non ho ancora ottenuto la media di più abbonati, per favore puoi fornire un link o un esempio. Grazie
Deepak Patidar,

2
observable1.subscribe (subscriber1), observable1.subscribe (subscriber2) - questo richiama la funzione più volte.
Benjamin Gruenbaum,

2
Si prega di modificare il tuo post e mostrare il testo vero e proprio, invece di screenshot. Altri non possono copiare e incollare dalle tue immagini e non possono aiutarti a correggere i numerosi errori grammaticali. Vedi qui per i dettagli. Grazie.
Pang

26

Anche se questa risposta è in ritardo, ho riassunto le differenze di seguito,

Osservabile:

  1. Osservabile è solo un functionche prende an observere restituisce un function Observer: an object with next, error.
  2. L'osservatore consente al subscribe/unsubscribesuo flusso di dati, emette il valore successivo all'osservatore, notifyl'osservatore errorse informa l'osservatore sulstream completion
  3. Observer fornisce a function to handle next value, errori e fine del flusso (eventi dell'interfaccia utente, risposte http, dati con socket Web).
  4. Funziona con multiple valuesil tempo
  5. È cancel-able/retry-ablee supporta operatori come map,filter,reduceecc.
  6. La creazione di un osservabile può essere - Observable.create()- restituisce osservabile che può invocare metodi su - Observer Observable.from()- converte un array o iterabile in - Observable Observable.fromEvent()- converte un evento in osservabile - Observable.fromPromise()- converte una promessa in osservabile - Observable.range()- restituisce una sequenza di numeri interi nell'intervallo specificato

Promessa :

  1. Una promessa rappresenta un compito che finirà in futuro;

  2. Le promesse diventano resolved by a value;

  3. Le promesse vengono rifiutate da eccezioni;

  4. No cancellablee ritornaa single value

  5. Una promessa espone una funzione (then)

    -quindi restituisce un nuovo promise;

    -consente che il attachmentdi quello verrà eseguito in base a state;

    - handlersdevono guaranteedessere eseguiti order attached;


20

Ho appena affrontato un problema in cui le promesse erano la soluzione migliore e la condivido qui per chiunque si imbatta in questa domanda nel caso in cui sia utile (questa era esattamente la risposta che stavo cercando prima):

In un progetto Angular2 ho un servizio che accetta alcuni parametri e restituisce un elenco di valori per popolare i menu a discesa in un modulo. Quando il componente del modulo viene inizializzato, devo chiamare lo stesso servizio più volte con parametri diversi per definire un numero di menu a discesa diversi, tuttavia se accendo semplicemente tutte le variabili per chiamare il servizio, solo l'ultimo riesce e l'errore di riposo su. Il servizio di recupero dal database poteva gestire solo una richiesta alla volta.

L'unico modo per popolare tutte le variabili del menu a discesa era chiamare il servizio in modo da impedire l'elaborazione di una nuova richiesta fino al termine dell'ultima richiesta e il meccanismo Promise / .then ha risolto il problema in modo corretto.

  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;
          })  }

Ho definito le funzioni nel componente, quindi ho chiamato initializeDropDowns () in ngOnInit.

La funzione fetchValueList restituisce un Promise, quindi la prima chiamata passa il primo listCode e quando il Promise si risolve, il valore di ritorno è nella variabile data nel blocco .then dove possiamo assegnarlo alla variabile this.firstValList. Poiché la funzione ha restituito dati, sappiamo che il servizio è terminato ed è possibile richiamare in modo sicuro con il secondo listCode, il valore restituito si trova nella variabile di dati nel blocco .then successivo e lo assegniamo alla variabile this.secondValList.

Possiamo concatenarlo tutte le volte che è necessario per popolare tutte le variabili e sull'ultimo blocco di codice semplicemente omettiamo l'istruzione return e il blocco termina.

Questo è un caso d'uso molto specifico in cui abbiamo un singolo servizio che deve essere chiamato più volte durante l'inizializzazione del componente e in cui il servizio deve completare il suo recupero e restituire un valore prima che possa essere richiamato di nuovo, ma in questo caso, il metodo Promise / .then era l'ideale.


3
Questo è certamente possibile anche con osservabili (di ordine superiore). Ad esempio, è possibile utilizzare scan()per creare un flusso di osservabili sequenziali. Tuttavia, il tuo approccio è forse più esplicito e più facile da capire.
lex82,

1
È possibile sostituire "then" con "switchMap" e fare esattamente la stessa cosa con osservabili.
Dr. C. Hilarius,

1
Il problema con switchMap, come ho capito, è che avvierà tutte le richieste in parallelo e attenderà fino a quando non torneranno tutte, quindi restituirà i valori alla funzione chiamante mentre nella mia situazione, ho un singolo server che non posso chiamare più volte in parallelo (poiché il server rilascerà richieste non finite quando arrivano nuove), quindi ho dovuto assicurarmi che ogni chiamata al servizio di database fosse completata prima di iniziare una nuova chiamata, e la Promessa / sembrava essere la migliore e forse l'unico modo per risolverlo.
Stephen R. Smith

1
Perché non hai usato la mergeMap concatenata? Per quanto ho capito il tuo codice, questo è piuttosto semplice e fa il lavoro come il tuo esempio. @ StephenR.Smith
Ore

1
@Ore Puoi aggiungere un esempio di codice che risolva lo stesso problema di un'altra risposta? Sarebbe un buon riferimento e potrebbe essere una buona opportunità di refactoring in futuro. Il requisito è che qualunque codice non possa chiamare il servizio back-end in parallelo, deve chiamare, attendere il valore restituito e chiamare nuovamente.
Stephen R. Smith,

20

Credo che tutte le altre risposte dovrebbero chiarire i tuoi dubbi. Tuttavia, volevo solo aggiungere che gli osservabili si basano sulla programmazione funzionale e trovo molto utili le funzioni che ne derivano come mappa, mappa piatta, riduzione, zip. La coerenza che il Web raggiunge soprattutto quando dipende dalle richieste API è un miglioramento brutale.

Consiglio vivamente questa documentazione , poiché è la documentazione ufficiale di reattiveX e trovo che sia la più chiara in circolazione.

Se vuoi entrare in osservabili, suggerirei questo post in 3 parti: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

Sebbene sia pensato per RxJava, i concetti sono gli stessi ed è davvero ben spiegato. Nella documentazione di reattiveX, si hanno le equivalenze per ciascuna funzione. Devi cercare RxJS.


18

Promettere:

  • Fornire un singolo valore futuro;
  • Non pigro;
  • Non cancellabile;

Osservabile:

  • Emette più valori nel tempo;
  • Pigro;
  • cancellabile;
  • Supporta operatori di mappa, filtro, riduzione e simili

Se lo si desidera, è possibile utilizzare promesse anziché osservabili quando si chiama HTTP in angolare.


16

Panoramica:

  • Sia le promesse che gli osservabili ci aiutano a gestire le operazioni asincrone. Possono richiamare determinati callback quando vengono eseguite queste operazioni asincrone.
  • Una promessa può gestire solo un evento, gli osservabili sono per flussi di eventi nel tempo
  • Le promesse non possono essere annullate una volta in sospeso
  • L'emissione di dati osservabili può essere trasformata mediante operatori

Puoi sempre usare un osservabile per affrontare il comportamento asincrono poiché un osservabile ha tutte le funzionalità offerte da una promessa (+ extra). Tuttavia, a volte questa funzionalità aggiuntiva offerta da Observables non è necessaria. Quindi sarebbe un costo aggiuntivo importare una libreria per usarli.

Quando utilizzare le promesse:

Usa le promesse quando hai una singola operazione asincrona di cui vuoi elaborare il risultato. Per esempio:

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

Quindi una promessa esegue del codice in cui si risolve o rifiuta. Se si chiama risoluzione o rifiuto, la promessa passa da uno stato in sospeso a uno stato risolto o rifiutato . Quando lo stato della promessa viene risolto then(), viene chiamato il metodo. Quando lo stato della promessa viene rifiutato, catch()viene chiamato il metodo.

Quando usare gli osservabili:

Usa gli osservabili quando c'è un flusso (di dati) nel tempo che devi gestire. Un flusso è una sequenza di elementi di dati che vengono resi disponibili nel tempo . Esempi di flussi sono:

  1. Eventi utente, ad esempio clic o eventi keyup. L'utente genera eventi (dati) nel tempo.
  2. Websocket, dopo che il client ha effettuato una connessione WebSocket al server, invia i dati nel tempo.

Nell'Osservabile si specifica quando si verifica l' evento successivo , quando si verifica un errore o quando l'Osservabile è completato . Quindi possiamo abbonarci a questo osservabile, che lo attiva e in questo abbonamento, possiamo trasmettere 3 callback (non è sempre necessario passare tutto). Un callback da eseguire per esito positivo, un callback per errore e un callback per completamento. Per esempio:

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

Quando si crea un osservabile richiede una funzione di callback che fornisce un osservatore come argomento. Su questo osservatore, è quindi possibile chiamare onNext, onCompleted, onError. Quindi, quando l'Osservabile è abbonato, chiamerà i callback corrispondenti passati nell'abbonamento.


9

Promessa: fornire un singolo valore futuro. Non pigro . Non annullabile. Rifiuterà o risolverà.

Osservabile: fornisce più valore futuro. Pigro Annullabile. Fornisce altri metodi mappa live, filtro, riduzione.


8

Somiglianza promessa vs osservabile prima

  1. Entrambi utilizzati per gestire il codice asincrono.
  2. Cerca un esempio promettente. Il costruttore Promise passa una funzione di riferimento di risoluzione che verrà chiamata quando viene chiamata con un certo valore al completamento di un'attività asincrona.

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

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

  1. Esempio osservabile ora. Anche qui passiamo una funzione all'osservabile, un osservatore per gestire l'attività asincrona. A differenza della risoluzione nella promessa, ha il seguente metodo e si abbona al posto di allora.

  2. Quindi entrambi gestiscono le attività asincrone. Ora vediamo la differenza.


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

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

Promessa vs differenza osservabile

Promettere

  1. Risolve o rifiuta un singolo valore e può gestire un'attività asincrona a singolo valore alla volta.
  2. Una promessa una volta risolto il valore asincrono che completa, non può più essere utilizzata. È solo una volta e qui non è all'altezza.
  3. Non cancellabile
  4. Nessun supporto rxjs per gli operatori.

Osservabile

  1. capacità di emettere più valori asincroni.
  2. Utilizzato per gestire il flusso di eventi o valori. Considerare di disporre di una serie di numerose attività o valori e che si desidera che ogni volta che si inserisce un valore, questo debba essere gestito automaticamente. Ogni volta che si inserisce un valore in questo array, tutti i suoi abbonati riceveranno automaticamente l'ultimo valore.
  3. Gli osservabili sono utili per osservare le modifiche di input, l'intervallo ripetuto, i valori di trasmissione a tutti i componenti figlio, le notifiche push del socket Web ecc.
  4. Può essere annullato utilizzando il metodo di annullamento dell'iscrizione in qualsiasi momento.
  5. Un'ultima buona parte che promette è il supporto per gli operatori rxjs. Hai molti operatori di pipe principalmente mappare, filtrare, switchMap, combinare più recenti ecc. Per trasformare i dati osservabili prima della sottoscrizione.

inserisci qui la descrizione dell'immagine



6

Sia le promesse che gli osservabili ci aiutano a gestire le operazioni asincrone. Possono richiamare determinati callback quando vengono eseguite queste operazioni asincrone.

Angular usa Observables che proviene da RxJS invece di promesse per gestire HTTP

Below are some important differences in promises & Observables.

differenza tra promesse e osservabili


1
I dati tabulati sembrano errati, il titolo dovrebbe essere scambiato
Derrick.X

1
Si prega di modificare il tuo post e mostrare il contenuto effettivo come testo invece di screenshot. Altri non possono copiare e incollare dalle tue immagini. Vedi qui per i dettagli. Grazie.
Pang

6

Una promessa emette un singolo evento quando un'attività asincrona termina o fallisce.

Un osservabile è come uno stream (in molte lingue) e consente di passare almeno zero o più eventi in cui è richiesto il callback per ogni evento.

Frequentemente osservabile è preferito rispetto a Promessa poiché fornisce i punti salienti di Promessa e altro. Con Observable non importa se devi gestire 0, 1 o vari eventi. È possibile utilizzare l'API simile per ciascun caso.

Promessa: promessa emette un singolo valore

Per esempio:

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

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

Osservabile: emette più valori per un periodo di tempo

Per esempio:

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

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

possiamo pensare a un osservabile come un flusso che emette più valori per un periodo di tempo e la stessa funzione di callback viene chiamata per ogni elemento emesso, quindi con un osservabile possiamo usare la stessa API per gestire dati asincroni. se tali dati vengono trasmessi come valore singolo o multipli per un certo periodo di tempo.

Promettere:

  • Una promessa non è pigra
  • Una promessa non può essere annullata

Osservabile:

  • Osservabile è pigro. "Osservabile" è lento. Non viene chiamato fino a quando non ci siamo iscritti.
  • Un osservabile può essere annullato usando il metodo unsubscribe ()
  • Un'aggiunta osservabile fornisce molti potenti operatori come mappa, foreach, filtro, riduzione, riprovare, riprovare, quando ecc.

Promesse angolari vs osservabili


5

Promise emette un singolo valore mentre Observable emette più valori. Quindi, durante la gestione di una richiesta HTTP, Promise può gestire una singola risposta per la stessa richiesta, ma cosa succede se ci sono più risposte alla stessa richiesta, allora dobbiamo usare Osservabile. Sì, Observable può gestire più risposte per la stessa richiesta.

Promettere

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

Produzione

Promise 1

Osservabile

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

Produzione

Observable 1
Observable 2
Observable 3

3

Di seguito sono riportate alcune importanti differenze nelle promesse e osservabili.

Promettere

  • Emette un solo valore
  • Non cancellabile
  • Non condivisibile
  • Sempre asincrono

Osservabile

  • Emette più valori
  • Esegue solo quando viene chiamato o qualcuno si sta iscrivendo
  • Può essere cancellabile
  • Può essere condiviso e sottoscritto quel valore condiviso da più abbonati. E tutti gli abbonati eseguiranno in un unico momento.
  • possibilmente asincrono

Per una migliore comprensione, consultare https://stackblitz.com/edit/observable-vs-promises


3

Vedo molte persone usare l'argomento secondo cui Osservabile è "cancellabile" ma è piuttosto banale rendere Promessa "cancellabile"

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


2

Risposta breve :

Osservabile è meglio , ha tutte le funzionalità Promises più funzionalità extra.


Risposta lunga:

promesse:

  • Utilizzare una volta "Restituisci dati una volta"
  • Nessun annullamento
  • Un ascoltatore
  • Nessun socket supporta un ascoltatore

Osservabile:

  • Restituisci i dati molte volte quando cambiano i dati
  • Supporto annulla
  • Presa di supporto
  • Supporta molti ascoltatori e avvisali quando cambiano i dati
  • Supporto mappa, filtro, riduzione

Non credo che si possa dire che gli osservabili siano oggettivamente migliori. Vi sono numerosi aspetti negativi di Observables indicati nelle varie risposte qui. Quelli che mi contraddistinguono sono la complessità di Observable e che non funzionano direttamente con waitit / async. Personalmente li trovo davvero difficili da lavorare perché non è possibile determinare il comportamento di un osservabile quando lo si utilizza: è necessario esaminare il codice che lo ha generato. Considerando che con una promessa, sai esattamente come funzionano, sempre. Ad esempio, a volte l'abbonamento a un osservabile ha effetti collaterali (ad esempio una richiesta http), ma a volte no.
Yona Appletree,

Per angolare, dipende dal tuo caso. per la maggior parte dei casi lavoreremo con servizi e alcuni dati che influenzeranno luoghi diversi, prese, cancellazione, mappa, filtro e riduzione. quindi sarà meglio in quei casi poiché le promesse non li sostengono. quindi di nuovo dipende dal tuo caso
Amr Ibrahim,

2

Mentre la risposta accettata è buona in generale, non penso che enfatizzi che quando si ha a che fare con componenti angolari si desidera quasi sempre usare un osservabile perché supporta l'annullamento. Le promesse non possono essere annullate e verranno risolte anche se il componente viene distrutto. L'angolare tende a perdonare fino a quando non lo è.

Ad esempio, qualsiasi rilevamento manuale delle modifiche su un componente distrutto causerà un'eccezione:

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();
  });
}

Se il componente viene distrutto prima che la promessa venga risolta, verrà visualizzato un attempt to use destroyed viewerrore quando la promessa viene risolta.

In alternativa, se si utilizzano osservabili con il modello takeUntil , non appena il componente viene distrutto, l'abbonamento verrà annullato.

Questo è un esempio un po 'inventato, ma l'esecuzione del codice per un componente che viene distrutto probabilmente porterà a bug. A meno che tu non voglia farlo per qualche motivo: p


2

Qualcosa in cui mi sono imbattuto che non era evidente da una prima lettura del tutorial e dei documenti era l'idea del multicast.

Assicurati di essere consapevole che, per impostazione predefinita, più abbonamenti attiveranno più esecuzioni in un osservabile. Più abbonamenti a una singola chiamata HTTP Osservabile attiverà più chiamate HTTP identiche a meno che tu .share()(abiliti il ​​multicast).

Una promessa ti obbliga a gestire una cosa alla volta, a scartare i suoi dati, a gestire le eccezioni, ha il supporto linguistico per cose interessanti come asincrono / attendi ed è piuttosto semplice.

Un osservabile ha molte campane e fischietti, ma devi capire il potere con cui stai lavorando o può essere usato in modo improprio.


2

Promettere:

Un gestore di eventi asincrono: l'oggetto Promessa rappresenta l'eventuale completamento (o errore) di un'operazione asincrona e il valore risultante.

Sintassi: new Promise (esecutore);

Per esempio:

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);

inserisci qui la descrizione dell'immagine

Informazioni su Promessa: ha una pipeline, quindi restituirà i valori una sola volta quando viene chiamato. è un gestore a senso unico, quindi una volta chiamato potresti non essere in grado di annullare. sintassi utile su cui giocare, quando () e poi ()

osservabili:

Gli osservabili sono raccolte pigre di più valori nel tempo. è davvero un ottimo approccio per le operazioni asincrone. può essere fatto con rxjs che ha il supporto multipiattaforma può usare con angolare / reagire ecc.

si comporta come stream liner. può essere multi pipeline. quindi, una volta definito, puoi abbonarti per ottenere risultati di ritorno in molti luoghi.

Sintassi: import * as Rx from "@reactivex/rxjs"; per init:

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

eccetera

sottoscrivere: RxLogger.getInstance();

Per esempio:

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));

dal momento che supporta multi pipeline è possibile abbonarsi risultati in posizioni diverse, inserisci qui la descrizione dell'immagine ha molte possibilità rispetto alle promesse.

Uso: ha più possibilità comemap, filter, pipe, map, concatMap etc


2

Le differenze fondamentali tra osservabili e promesse sono:

inserisci qui la descrizione dell'immagine


2
Si prega di modificare il tuo post e mostrare il contenuto effettivo come testo invece di screenshot. Altri non possono copiare e incollare dalle tue immagini. Vedi qui per i dettagli. Grazie.
Pang

1

Gli osservabili sono spesso paragonati alle promesse. Ecco alcune differenze chiave:

Gli osservabili sono dichiarativi; il calcolo non inizia fino alla sottoscrizione. Le promesse si eseguono immediatamente al momento della creazione. Ciò rende osservabili utili per definire ricette che possono essere eseguite ogni volta che è necessario il risultato.

Gli osservabili forniscono molti valori. Le promesse ne forniscono una. Ciò rende osservabili utili per ottenere più valori nel tempo.

Gli osservabili distinguono tra concatenamento e abbonamento. Le promesse hanno solo clausole .then (). Ciò rende osservabili utili per la creazione di complesse ricette di trasformazione che possono essere utilizzate da altre parti del sistema, senza causare l'esecuzione del lavoro.

Osservabili iscriviti () è responsabile della gestione degli errori. Le promesse spingono errori alle promesse dei bambini. Ciò rende osservabili utili per la gestione centralizzata e prevedibile degli errori.

Questa è la differenza più semplice che potresti trovare sui documenti ANGULAR.IO. la risposta di riposo è data dalla maggior parte è corretta al suo posto


1
  1. Le promesse si concentrano solo per singoli valori o si risolvono, le osservabili sono flussi di dati.

  2. Gli osservabili possono essere cancellati ma le promesse non possono essere cancellate.

Il meno conosciuto, almeno per me è

  1. Le promesse sono sempre di natura asincrona, ma gli osservabili possono essere sia sincroni che asincroni.

0
  1. una Promessa è desiderosa, mentre una Osservabile è pigra,
  2. una Promessa è sempre asincrona, mentre un osservabile può essere sincrono o asincrono,
  3. una Promessa può fornire un singolo valore, mentre una Osservabile è un
    flusso di valori (da 0 a più valori),
  4. è possibile applicare operatori RxJS a un osservabile per ottenere un nuovo flusso su misura.

-1

Osservabili e promesse ci stanno aiutando a lavorare con le funzionalità asincrone in JavaScript / dattiloscritto. Sono molto simili in molti casi, tuttavia ci sono ancora alcune differenze tra loro.

inserisci qui la descrizione dell'immagine


1
Si prega di modificare il tuo post e mostrare il testo vero e proprio, invece di screenshot. Altri non possono copiare e incollare dalle tue immagini. Vedi qui per i dettagli. Grazie.
Pang

Tranne il fatto che non è un codice ma semplici informazioni, quindi penso che sia giusto pubblicarlo come immagine
Alator,

1
smetti di copiare e incollare dai video di YouTube di Kudvenkat. Downvote da me! :)
Pratik

-2

Ci sono già molte risposte su questo argomento, quindi non ne aggiungerei una ridondante.

Ma a qualcuno che ha appena iniziato a studiare Osservabile / Angolare e si chiede quale utilizzare utilizzare rispetto a Promessa , ti consiglierei di mantenere tutto Osservabile e convertire tutte le Promesse esistenti nel tuo progetto in Osservabili.

Semplicemente perché la stessa struttura angolare e la sua comunità utilizzano tutti Osservabile. Quindi sarebbe utile quando si integrano servizi quadro o moduli di terze parti e si concatena tutto insieme.


Mentre apprezzo tutti i downvotes ma insisto ancora sulla mia opinione sopra a meno che qualcuno non abbia inserito un commento appropriato per elencare alcuni scenari che potrebbero essere ancora utili nel tuo progetto angolare per utilizzare Promises over Observables.

Ovviamente, nessuna opinione è corretta al 100% in tutti i casi, ma almeno credo che il 98% delle volte, per i normali progetti commerciali implementati nel quadro angolare, Observable sia la strada giusta da percorrere.

Anche se non ti piace all'inizio del tuo semplice progetto di hobby, realizzerai presto quasi tutti i componenti con cui interagisci in Angular, e la maggior parte del framework di terze parti che utilizza Angular utilizza Observables e quindi ha finito per convertire costantemente la tua promessa in osservabile per comunicare con loro.

Tali componenti includono ma non sono limitati a: HttpClient, Generatore di moduli, Moduli / finestre di dialogo di materiali angolari, Ngrx store / effects e ngx-bootstrap.

In effetti, l'unico ecosistema Promise from Angular che ho affrontato negli ultimi 2 anni è APP_INITIALIZER.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.