What is the difference between Promises and Observables?

后端 未结 30 2652
小鲜肉
小鲜肉 2020-11-21 23:48

What is the difference between Promise and Observable in Angular?

An example on each would be helpful in understanding both the cases. In w

相关标签:
30条回答
  • 2020-11-22 00:18

    There are lots of answers on this topic already so I wouldn't add a redundant one.

    But to someone who just started learning Observable / Angular and wonders which one to use compare with Promise, I would recommend you keep everything Observable and convert all existing Promises in your project to Observable.

    Simply because Angular framework itself and it's community are all using Observable. So it would be beneficial when you integrate framework services or 3rd party modules and chaining everything together.


    While I appreciate all the downvotes but I still insist my opinion above unless someone put a proper comment to list a few scenarios that might still be useful in your Angular project to use Promises over Observables.

    Of course, no opinion is 100% correct in all cases but at least I think 98% of the time for regular commercial projects implemented in Angular framework, Observable is the right way to go.

    Even if you don't like it at the starting point of your simple hobby project, you'll soon realise almost all components you interact with in Angular, and most of the Angular friendly 3rd party framework are using Observables, and then you'll ended up constantly converting your Promise to Observable in order to communicate with them.

    Those components includes but not limited to: HttpClient, Form builder, Angular material modules/dialogs, Ngrx store/effects and ngx-bootstrap.

    In fact, the only Promise from Angular eco-system I dealt with in the past 2 years is APP_INITIALIZER.

    0 讨论(0)
  • 2020-11-22 00:19

    Promises

    1. Definition: Helps you run functions asynchronously, and use their return values (or exceptions) but only once when executed.
    2. Not Lazy
    3. Not cancellable( There are Promise libraries out there that support cancellation, but ES6 Promise doesn't so far). The two possible decisions are
      • Reject
      • Resolve
    4. Cannot be retried(Promises should have access to the original function that returned the promise to have a retry capability, which is a bad practice)

    Observables

    1. Definition: Helps you run functions asynchronously, and use their return values in a continuous sequence(multiple times) when executed.
    2. By default, it is Lazy as it emits values when time progresses.
    3. Has a lot of operators which simplifies the coding effort.
    4. One operator retry can be used to retry whenever needed, also if we need to retry the observable based on some conditions retryWhen can be used.

      Note: A list of operators along with their interactive diagrams is available here at RxMarbles.com

    0 讨论(0)
  • 2020-11-22 00:19

    Observables are often compared to promises. Here are some key differences:

    Observables are declarative; computation does not start until subscription. Promises execute immediately on creation. This makes observables useful for defining recipes that can be run whenever you need the result.

    Observables provide many values. Promises provide one. This makes observables useful for getting multiple values over time.

    Observables differentiate between chaining and subscription. Promises only have .then() clauses. This makes observables useful for creating complex transformation recipes to be used by other parts of the system, without causing the work to be executed.

    Observables subscribe() is responsible for handling errors. Promises push errors to the child promises. This makes observables useful for centralized and predictable error handling.

    That is the most simplest difference that you may found on ANGULAR.IO docs. rest answer is given by most is correct at its own place

    0 讨论(0)
  • 2020-11-22 00:20

    Promise vs Observable similarity first

    1. Both used to handle async code.
    2. Please look for promise example. Promise constructor passes a resolve reference function which will get called when it gets called with some value upon completion of some async task.

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

    1. Observable example now. Here also we pass a function to observable, an observer to handle the async task. Unlike resolve in the promise it has the following method and subscribes in place of then.

    2. So both handles async tasks. Now let's see the difference.


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

    Promise vs Observable difference

    Promise

    1. It resolves or reject a single value and can handle a single value async task at a time.
    2. A promise once resolved the async value it completes, can no longer be used.its just one-time use and here it falls short.
    3. Not cancellable
    4. No rxjs support for operators.

    Observable

    1. ability to emit multiple asynchronous values.
    2. Used to handle the stream of events or values. Consider you have an array of numerous tasks or values, and you want every time value is inserted into this it should be handled automatically. Anytime you push a value into this array, all of its subscribers will receive the latest value automatically.
    3. Observables are useful for observing input changes, repeated interval, broadcast values to all child components, web socket push notifications etc.
    4. Can be cancelled using unsubscribe method anytime.
    5. One more last good part that promise that has is support for rxjs operators. You have many pipe operators majorly map, filter, switchMap, combineLatest etc. to transform observable data before subscribing.


    0 讨论(0)
  • 2020-11-22 00:21

    Both Promises and Observables provide us with abstractions that help us deal with the asynchronous nature of our applications. The difference between them was pointed out clearly by @Günter and @Relu.

    Since a code snippet is worth a thousand words, let go through the below example to understand them easier.

    Thanks @Christoph Burgdorf for the awesome article


    Angular uses Rx.js Observables instead of promises for dealing with HTTP.

    Suppose that you are building a search function that should instantly show you results as you type. Sound familiar but there are a lot of challenges that come with that task.

    • We don't want to hit the server endpoint every time user presses a key, it should flood them with a storm of HTTP requests. Basically, we only want to hit it once the user has stopped typing instead of with every keystroke.
    • Don’t hit the search endpoint with the same query params for subsequent requests.
    • Deal with out-of-order responses. When we have multiple requests in-flight at the same time we must account for cases where they come back in unexpected order. Imagine we first type computer, stop, a request goes out, we type car, stop, a request goes out. Now we have two requests in-flight. Unfortunately, the request that carries the results for computer comes back after the request that carries the results for car.

    The demo will simply consist of two files: app.ts and wikipedia-service.ts. In a real world scenario, we would most likely split things further up, though.


    Below is Promise-based implementation that doesn’t handle any of the described edge cases.

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

    We are injecting the Jsonp service to make a GET request against the Wikipedia API with a given search term. Notice that we call toPromise in order to get from an Observable<Response> to a Promise<Response>. Eventually end up with a Promise<Array<string>> as the return type of our search method.

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

    Not much of a surprise here either. We inject our WikipediaService and expose it’s functionality via a search method to the template. The template simply binds to keyup and calls search(term.value).

    We unwrap the result of the Promise that the search method of the WikipediaService returns and expose it as a simple Array of strings to the template so that we can have *ngFor loop through it and build up a list for us.

    See the example of Promise-based implementation on Plunker


    Where Observables really shine

    Let’s change our code to not hammer the endpoint with every keystroke but instead only send a request when the user stopped typing for 400 ms

    To unveil such super powers we first need to get an Observable<string> that carries the search term that the user types in. Instead of manually binding to the keyup event, we can take advantage of Angular’s formControl directive. To use this directive, we first need to import the ReactiveFormsModule into our application module.

    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 {}
    

    Once imported, we can use formControl from within our template and set it to the name "term".

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

    In our component, we create an instance of FormControl from @angular/form and expose it as a field under the name term on our component.

    Behind the scenes, term automatically exposes an Observable<string> as property valueChanges that we can subscribe to. Now that we have an Observable<string>, overcoming the user input is as easy as calling debounceTime(400) on our Observable. This will return a new Observable<string> that will only emit a new value when there haven’t been coming new values for 400ms.

    export class App {
      items: Array<string>;
      term = new FormControl();
      constructor(private wikipediaService: WikipediaService) {
        this.term.valueChanges
                  .debounceTime(400)        // wait for 400ms pause in events
                  .distinctUntilChanged()   // ignore if next search term is same as previous
                  .subscribe(term => this.wikipediaService.search(term).then(items => this.items = items));
      }
    }
    

    It would be a waste of resources to send out another request for a search term that our app already shows the results for. All we have to do to achieve the desired behavior is to call the distinctUntilChanged operator right after we called debounceTime(400)

    See the example of Observable implementation on Plunker

    For dealing with out-of-order responses, please check the full article http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

    As far as I am using Http in Angular, I agree that in the normal use cases there is not much difference when using Observable over Promise. None of the advantages are really relevant here in practice. Hope I can see some advanced use case in the future :)


    Learn more

    • https://angular-2-training-book.rangle.io/handout/observables/
    • https://angular.io/tutorial/toh-pt6#observables
    0 讨论(0)
  • 2020-11-22 00:21

    Even though this answer is late, i have summarized the differences below,

    Observable:

    1. Observable is just a function that takes an observer and returns a function Observer: an object with next, error.
    2. Observer allows to subscribe/unsubscribe to its data stream, emit next value to the observer, notify the observer about errors and inform the observer about the stream completion
    3. Observer provides a function to handle next value,errors and end of stream(ui events,http responses,data with web sockets).
    4. Works with multiple values over time
    5. It is cancel-able/retry-able and supports operators such as map,filter,reduce etc.
    6. Creating an Observable can be -Observable.create() - returns Observable that can invoke methods on -Observer Observable.from() - converts an array or iterable into -Observable Observable.fromEvent() - converts an event into Observable -Observable.fromPromise() - converts a Promise into Observable -Observable.range() - returns a sequence of integers in the specified range

    Promise:

    1. A promise represents a task that will finish in the future;

    2. Promises become resolved by a value;

    3. Promises get rejected by exceptions;

    4. Not cancellable and it returns a single value

    5. A promise expose a function (then)

      -then returns a new promise;

      -allows for the attachment of that will be executed based on state;

      -handlers are guaranteed to execute in order attached;

    0 讨论(0)
提交回复
热议问题