docs(http): refine observables story

closes #799
This commit is contained in:
Ward Bell 2016-02-02 11:22:48 -08:00
parent 705a5d9e93
commit 8960b6729f
5 changed files with 54 additions and 34 deletions

View File

@ -25,7 +25,7 @@
"rxjs": "5.0.0-beta.0", "rxjs": "5.0.0-beta.0",
"zone.js": "0.5.10", "zone.js": "0.5.10",
"a2-in-memory-web-api": "^0.1.0", "a2-in-memory-web-api": "^0.1.1",
"bootstrap": "^3.3.6" "bootstrap": "^3.3.6"
}, },

View File

@ -2,9 +2,10 @@
import {Component} from 'angular2/core'; import {Component} from 'angular2/core';
import {JSONP_PROVIDERS} from 'angular2/http'; import {JSONP_PROVIDERS} from 'angular2/http';
import {Observable} from 'rxjs/Observable'; import {Observable} from 'rxjs/Observable';
// #docregion import-subject // #docregion import-observer
import {Subject} from 'rxjs/Subject'; import {Observer} from 'rxjs/Observer';
// #enddocregion import-subject // #enddocregion import-observer
import {WikipediaService} from './wikipedia.service'; import {WikipediaService} from './wikipedia.service';
@Component({ @Component({
@ -25,19 +26,21 @@ export class WikiSmartComponent {
constructor (private _wikipediaService: WikipediaService) { } constructor (private _wikipediaService: WikipediaService) { }
// #docregion subject search: (value: string) => void;
private _searchTermStream = new Subject();
search(value: string){ // #docregion observable-create
this._searchTermStream.next(value); private _searchTermStream: Observable<string> =
} Observable.create(
// #enddocregion subject // #docregion subscribe-fn
(observer:Observer<string>) => this.search = (term) => observer.next(term)
// #enddocregion subscribe-fn
);
// #enddocregion observable-create
// #docregion observable // #docregion observable-operators
items = this._searchTermStream items:Observable<string[]> = this._searchTermStream
.debounceTime(300) .debounceTime(300)
.distinctUntilChanged() .distinctUntilChanged()
.switchMap((term:string) => this._wikipediaService.search(term)); .switchMap((term:string) => this._wikipediaService.search(term));
// #enddocregion observable-operators
// #enddocregion observable
} }

View File

@ -2,6 +2,7 @@
import {Component} from 'angular2/core'; import {Component} from 'angular2/core';
import {JSONP_PROVIDERS} from 'angular2/http'; import {JSONP_PROVIDERS} from 'angular2/http';
import {Observable} from 'rxjs/Observable'; import {Observable} from 'rxjs/Observable';
import {WikipediaService} from './wikipedia.service'; import {WikipediaService} from './wikipedia.service';
@Component({ @Component({

View File

@ -49,8 +49,8 @@
}, },
"server-communication": { "server-communication": {
"title": "Server Communication", "title": "Http Client",
"intro": "Learn to build applications that talk to a server." "intro": "Talk to a remote server with the Angular Http Client."
}, },
"lifecycle-hooks": { "lifecycle-hooks": {

View File

@ -491,17 +491,32 @@ figure.image-display
+makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', null, 'app/wiki/wiki-smart.component.ts') +makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', null, 'app/wiki/wiki-smart.component.ts')
:marked :marked
We made no changes to the template or metadata, confining them all to the component class. We made no changes to the template or metadata, confining them all to the component class.
Let's review those changes.
The first step turns the user's search box entries into the *subject* of an observable. ### Create the search term Observable
We import the `Subject` class from the RxJS observable library:
+makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'import-subject') We import the `Observer` symbol from the RxJS observable library to get the type information:
+makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'import-observer')
:marked :marked
After every keystroke we pump the search box value into the private `_searchTermStream` subject, creating a stream of search term strings. The first real step turns the user's search box entries into an observable stream of search terms.
+makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'subject')(format='.') We create a private `Observable` called `_searchTermStream`, driven by a *subscribe* function that
feeds user search terms to the observable.
+makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'observable-create')(format='.')
:marked :marked
The *subscribe* function sets the component's `search` method to a function that updates
the observable's `observer` with search terms.
+makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'subscribe-fn')(format='.')
:marked
The search box `keyup` events are still bound to this `search` method in the template.
After every keystroke the binding pumps the search box value into the `_searchTermStream` observable,
creating a stream of search term strings.
### Listen for search terms
Earlier, we passed each search term directly to the service and bound the template to the service results. Earlier, we passed each search term directly to the service and bound the template to the service results.
Now we listen to the *stream of terms*, manipulating the stream before it reaches the `WikipediaService`. Now we listen to the *stream of terms*, manipulating the stream before it reaches the `WikipediaService`.
+makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'observable')(format='.') +makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'observable-operators')(format='.')
:marked :marked
We wait for the user to stop typing for at least 300 milliseconds We wait for the user to stop typing for at least 300 milliseconds
([debounce](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/debounce.md)). ([debounce](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/debounce.md)).
@ -509,14 +524,15 @@ figure.image-display
([distinctUntilChanged](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/distinctuntilchanged.md)). ([distinctUntilChanged](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/distinctuntilchanged.md)).
The `WikipediaService` returns a separate observable of strings (`Observable<string[]>`) for each request. The `WikipediaService` returns a separate observable of strings (`Observable<string[]>`) for each request.
We could have multiple requests "in flight", all awaiting the server's reply, We could have multiple requests *in flight*, all awaiting the server's reply,
which means multiple *observables-of-strings* could arrive at any moment in any order. which means multiple *observables-of-strings* could arrive at any moment in any order.
We rely on [switchMap](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/flatmaplatest.md) The [switchMap](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/flatmaplatest.md)
(formerly known as `flatMapLatest`) to re-arrange these observables in their original-request order. (formerly known as `flatMapLatest`) returns a new observable that combines these `WikipediaService` observables,
re-arranges them in their original request order,
and delivers to subscribers only the most recent search results.
The `switchmap` operator ensures that the component's `items` property is always set to the truly latest `WikipediaService` observable. The displayed list of search results stays in sync with the user's sequence of search terms.
Consequently, the displayed list of search results stays in sync with the user's sequence of search terms.
<a id="in-mem-web-api"></a> <a id="in-mem-web-api"></a>
.l-main-section .l-main-section