What is the difference between Promise
and Observable
in Angular?
An example on each would be helpful in understanding both the cases. In w
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
.
Promises
Observables
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
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
const promise = new Promise(resolve => {
setTimeout(() => {
resolve("Hello from a Promise!");
}, 2000);
});
promise.then(value => console.log(value));
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.
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
Observable
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.
HTTP
requests. Basically, we only want to hit it once the user has stopped typing instead of with every keystroke.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
Even though this answer is late, i have summarized the differences below,
Observable:
function
that takes an observer
and returns a function Observer: an object with next, error.
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
function to handle next value
,errors and
end of stream(ui events,http responses,data with web sockets).multiple values
over timecancel-able/retry-able
and supports operators such as map,filter,reduce
etc.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 rangePromise:
A promise represents a task that will finish in the future;
Promises become resolved by a value
;
Promises get rejected by exceptions;
Not cancellable
and it returns a single value
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
;