Enhance Web Development
Angular 2
Observables et RxJS
- Reactive avec des Observables
- Qu'est-ce que RxJS ?
- Les opérateurs les plus communs
- Pipes Async
Reactive avec des Observables
- Dans le pattern Observer, un "object" (appelé le sujet), conserve une liste de ses "dependants" (appelé "observers") et les notifie automatiquement à chaque changement de "state"
- C'est ce qu'on appelle une "push strategy" (vs "pull/polling strategy")
Qu'est-ce que RxJS ?
- Une librairie pour composer des programmes asynchrone et basés sur les évènements en utilisant des collections d'Observable
- Un nombre énorme d'opérateur pour transformer le flux de donnée
Un peu de lecture :-)
Exemple basique
/* Get stock data somehow */
const source = getAsyncStockData()
const subscription = source
.filter(quote => quote.price > 30)
.map(quote => quote.price)
.subscribe(
price => console.log(`Prices higher than $30: ${price}`),
err => console.log(`Something went wrong: ${err.message}`)
)
/* When we're done */
subscription.dispose()
Les opérateurs les plus communs
- map
- filter
- scan
- debounce
- distinctUntilChanged
- comineLatest
- flatMap
Marbles
map
map
// Array
var numbers = [1, 2, 3]
var roots = numbers.map(Math.sqrt)
// roots is now [1, 4, 9], numbers is still [1, 2, 3]
// Observable
var source = Observable.range(1, 3)
.map(x => x * x)
var subscription = source.subscribe(
x => console.log('Next: ' + x),
err => console.log('Error: ' + err), () => console.log('Completed')
)
// => Next: 1
// => Next: 4
// => Next: 9
// => Completed
filter
filter
// Array
var filtered = [12, 5, 8, 130, 44]
.filter(x => x >= 10)
// filtered is [12, 130, 44]
// Observable
var source = Observable.range(0, 5)
.filter(x => x % 2 === 0)
var subscription = source.subscribe(
x => console.log('Next: ' + x),
err => console.log('Error: ' + err),
() => console.log('Completed')
)
// => Next: 0
// => Next: 2
// => Next: 4
// => Completed
scan
scan
var source = Observable.range(1, 3)
.scan((acc, x) => acc + x)
var subscription = source.subscribe(
x => console.log('Next: ' + x),
err => console.log('Error: ' + err),
() => console.log('Completed')
)
// => Next: 1
// => Next: 3
// => Next: 6
// => Completed
debounce
debounce
var array = [
800,
700,
600,
500
]
let source = Observable.for(array, function (x) { return Observable.timer(x) })
.map(function(x, i) { return i; })
.debounce(function (x) { return Observable.timer(700); })
var subscription = source.subscribe(
x => console.log('Next: ' + x),
err => console.log('Error: ' + err),
() => console.log('Completed')
)
// => Next: 0
// => Next: 3
// => Completed
distinctUntilChanged
distinctUntilChanged
var source = Observable.of(42, 42, 24, 24)
.distinctUntilChanged();
var subscription = source.subscribe(
x => console.log('Next: ' + x),
err => console.log('Error: ' + err),
() => console.log('Completed')
)
// => Next: 42
// => Next: 24
// => Completed
distinctUntilChanged
distinctUntilChanged
var source1 = Observable.interval(100)
.map(function (i) { return 'First: ' + i; })
var source2 = Observable.interval(150)
.map(function (i) { return 'Second: ' + i; })
// Combine latest of source1 and source2 whenever either gives a value
var source = Observable.combineLatest(
source1,
source2
).take(4)
var subscription = source.subscribe(
x => console.log('Next: ' + JSON.stringify(x)),
err => console.log('Error: ' + err),
() => console.log('Completed')
)
// => Next: ["First: 0","Second: 0"]
// => Next: ["First: 1","Second: 0"]
// => Next: ["First: 1","Second: 1"]
// => Next: ["First: 2","Second: 1"]
// => Completed
flatMap
flatMap
var source = Observable.range(1, 2)
.flatMap(function (x) {
return Observable.range(x, 2)
})
var subscription = source.subscribe(
x => console.log('Next: ' + x),
err => console.log('Error: ' + err),
() => console.log('Completed')
)
// => Next: 1
// => Next: 2
// => Next: 2
// => Next: 3
// => Completed
Les pipes async
- Permet de résoudre directement des données asynchrones dans la vue (observable/promises)
- Evite le processus manuel de se subscribe à une méthode asynchrone dans le composant
- On peut donc chainer les opérateur sur l'observable dans le composant et laisser la vue subscribe
Les pipes async
@Component({
selector: 'my-app',
template: `
<div>
<items-list [items]="items | async"
(selected)="selectItem($event)"
(deleted)="deleteItem($event)">
</items-list>
</div>
`,
directives: [ItemList],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class App {
items: Observable<Array<Item>>;
constructor(private itemsService: ItemsService) {
this.items = itemsService.items;
}
}
More about change detection
http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html
Demo time !
Défi
- Convertir tout les appels à Observable.toPromise en simple Observable
- Appliquer les opérateurs communs
Angular 2 - RxJS
By Benjamin LONGEARET
Angular 2 - RxJS
- 1,076