Introduction to Reactive Extensions
Need to learn about Observables, use this instead of promises when using asycnhronous operations like making ajax calls to server. Its confusing, therefore dedicating whole section to this topic.
Reactive Extensions: a library for composing asynchronous and event based programs using observables sequences and LINQ style query operators.
What?
Keep it simple.
Reactive extensions require its own cost, its a comprehensive library and has nothing to do with angular. If you are interested, go to reactivex.io
It works with other languages.
Angular team worked with reactivex especially when connecting to server.
In index.html we have reference to Rx.js ???
At the core of Reactive Extensions, we have Observables which represent a asynchronous data stream. What are they? DOM events. e.g keyup event from a textbox
Or web sockets,
Or Web workers, used to create bkgrd tasks in JS applications.
Finally, ajax calls.
Think of Observable as Collection.
We observe them and are notified when data arrives
function (newData){
...
}
Creating Observables
import { Component, ViewChild, ElementRef } from '@angular/core';
import { Observable } from 'rxjs/Rx';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `
<input #search type="text" class="form-control">
`
})
export class AppComponent {
@ViewChild('search')
search:ElementRef;
ngAfterViewInit() {
var keyups = Observable.fromEvent(this.search.nativeElement, "keyup");
keyups.subscribe(data => console.log(data));
}
}
Observable Operators
So what's the benefit of an observable stream?
Observables provides operators to transform, filter, aggregate and combine them.
Suppose we just want the text, not the actual DOM object.
app.component.ts
import { Component, ViewChild, ElementRef } from '@angular/core';
import { Observable } from 'rxjs/Rx';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `
<input #search type="text" class="form-control">
`
})
export class AppComponent {
@ViewChild('search')
search:ElementRef;
ngAfterViewInit() {
var keyups = Observable.fromEvent(this.search.nativeElement, "keyup")
.map((e:any) => e.target.value) // get text
.filter(text => text.length >= 3) // only receive observable when text is 3 char or longer
.debounceTime(400) //
.distinctUntilChanged(); // receive observable only when text is changed
keyups.subscribe(data => console.log(data));
}
}
'map' operator, takes an input and transform it.
Transforming Observables
import { Component, ViewChild, ElementRef } from '@angular/core';
import { Observable } from 'rxjs/Rx';
@Component({
moduleId: module.id,
selector: 'app-root',
template: `
<input #search type="text" class="form-control">
`
})
export class AppComponent {
@ViewChild('search')
search:ElementRef;
ngAfterViewInit() {
var keyups = Observable.fromEvent(this.search.nativeElement, "keyup")
.map((e:any) => e.target.value) // get text
.filter(text => text.length >= 3) // only receive observable when text is 3 char or longer
.debounceTime(400) //
.distinctUntilChanged()
.flatMap(searchTerm => {
var url = "https://api.spotify.com/v1/search?type=artist&q=" + searchTerm;
var promise = jQuery.getJSON(url);
return Observable.fromPromise(promise);
}); // above 3 lines should be in another method in service for better separation of concerns
var subscription = keyups.subscribe(data => console.log(data));
// to cancel subscription.
//subscription.unsubscribe();
}
}
Importing operators
No comments:
Post a Comment