diff --git a/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart b/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart index 0c946d9a46..1daedc2d8c 100644 --- a/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart +++ b/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart @@ -47,9 +47,6 @@ class HeroService { // #docregion extract-data dynamic _extractData(Response res) { - if (res.statusCode < 200 || res.statusCode >= 300) { - throw new Exception('Response status: ${res.statusCode}'); - } var body = JSON.decode(res.body); // TODO: once fixed, https://github.com/adaojunior/http-in-memory-web-api/issues/1 // Drop the `?? body` term diff --git a/public/docs/_examples/server-communication/ts/app/add-rxjs-operators.ts b/public/docs/_examples/server-communication/ts/app/add-rxjs-operators.ts new file mode 100644 index 0000000000..1381b30cd9 --- /dev/null +++ b/public/docs/_examples/server-communication/ts/app/add-rxjs-operators.ts @@ -0,0 +1,9 @@ +// #docregion +// import 'rxjs/Rx'; // adds ALL RxJS operators to Observable + +// Just the Observable operators we need for THIS app. +import 'rxjs/add/operator/catch'; +import 'rxjs/add/operator/debounceTime'; +import 'rxjs/add/operator/distinctUntilChanged'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/switchMap'; diff --git a/public/docs/_examples/server-communication/ts/app/hero-data.ts b/public/docs/_examples/server-communication/ts/app/hero-data.ts index 29f58fe663..ad10b464c7 100644 --- a/public/docs/_examples/server-communication/ts/app/hero-data.ts +++ b/public/docs/_examples/server-communication/ts/app/hero-data.ts @@ -2,10 +2,10 @@ export class HeroData { createDb() { let heroes = [ - { "id": "1", "name": "Windstorm" }, - { "id": "2", "name": "Bombasto" }, - { "id": "3", "name": "Magneta" }, - { "id": "4", "name": "Tornado" } + { id: '1', name: 'Windstorm' }, + { id: '2', name: 'Bombasto' }, + { id: '3', name: 'Magneta' }, + { id: '4', name: 'Tornado' } ]; return {heroes}; } diff --git a/public/docs/_examples/server-communication/ts/app/main.ts b/public/docs/_examples/server-communication/ts/app/main.ts index bbc025eab8..7fa98321f0 100644 --- a/public/docs/_examples/server-communication/ts/app/main.ts +++ b/public/docs/_examples/server-communication/ts/app/main.ts @@ -6,8 +6,8 @@ import { HTTP_PROVIDERS } from '@angular/http'; // #enddocregion http-providers // #docregion import-rxjs -// Add all operators to Observable -import 'rxjs/Rx'; +// Add the RxJS Observable operators we need in this app. +import './add-rxjs-operators'; // #enddocregion import-rxjs import { TohComponent } from './toh/toh.component'; diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.1.ts b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.1.ts index b9ac4ade37..3e4c3c6bf2 100644 --- a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.1.ts +++ b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.1.ts @@ -28,7 +28,7 @@ export class HeroListComponent implements OnInit { } addHero (name: string) { - if (!name) {return;} + if (!name) { return; } this.heroService.addHero(name) .then( hero => this.heroes.push(hero), diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts index 67a7b4f0de..2cb1689e01 100644 --- a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts +++ b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts @@ -31,7 +31,7 @@ export class HeroListComponent implements OnInit { // #docregion addHero addHero (name: string) { - if (!name) {return;} + if (!name) { return; } this.heroService.addHero(name) .subscribe( hero => this.heroes.push(hero), diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero.service.1.ts b/public/docs/_examples/server-communication/ts/app/toh/hero.service.1.ts index 04b7c476a6..a6da29514a 100644 --- a/public/docs/_examples/server-communication/ts/app/toh/hero.service.1.ts +++ b/public/docs/_examples/server-communication/ts/app/toh/hero.service.1.ts @@ -34,16 +34,14 @@ export class HeroService { } private extractData(res: Response) { - if (res.status < 200 || res.status >= 300) { - throw new Error('Bad response status: ' + res.status); - } let body = res.json(); return body.data || { }; } private handleError (error: any) { - // In a real world app, we might send the error to remote logging infrastructure - let errMsg = error.message || 'Server error'; + // In a real world app, we might use a remote logging infrastructure + // We'd also dig deeper into the error to get a better message + let errMsg = error.message || error.statusText || 'Server error'; console.error(errMsg); // log to console instead return Promise.reject(errMsg); } diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts b/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts index c470da425e..fcc0348c05 100644 --- a/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts +++ b/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts @@ -29,7 +29,7 @@ export class HeroService { // #enddocregion error-handling, http-get, v1 // #docregion addhero, addhero-sig - addHero (name: string): Observable { + addHero (name: string): Observable { // #enddocregion addhero-sig let body = JSON.stringify({ name }); let headers = new Headers({ 'Content-Type': 'application/json' }); @@ -43,9 +43,6 @@ export class HeroService { // #docregion v1, extract-data private extractData(res: Response) { - if (res.status < 200 || res.status >= 300) { - throw new Error('Response status: ' + res.status); - } let body = res.json(); return body.data || { }; } @@ -54,7 +51,8 @@ export class HeroService { // #docregion error-handling private handleError (error: any) { // In a real world app, we might use a remote logging infrastructure - let errMsg = error.message || 'Server error'; + // We'd also dig deeper into the error to get a better message + let errMsg = error.message || error.statusText || 'Server error'; console.error(errMsg); // log to console instead return Observable.throw(errMsg); } diff --git a/public/docs/_examples/server-communication/ts/app/wiki/wiki-smart.component.ts b/public/docs/_examples/server-communication/ts/app/wiki/wiki-smart.component.ts index a91f03124b..55485b8ff4 100644 --- a/public/docs/_examples/server-communication/ts/app/wiki/wiki-smart.component.ts +++ b/public/docs/_examples/server-communication/ts/app/wiki/wiki-smart.component.ts @@ -1,3 +1,4 @@ +/* tslint:disable:member-ordering */ // #docregion import { Component } from '@angular/core'; import { JSONP_PROVIDERS } from '@angular/http'; @@ -20,7 +21,7 @@ import { WikipediaService } from './wikipedia.service';
  • {{item}}
  • `, - providers:[JSONP_PROVIDERS, WikipediaService] + providers: [JSONP_PROVIDERS, WikipediaService] }) export class WikiSmartComponent { @@ -29,13 +30,13 @@ export class WikiSmartComponent { // #docregion subject private searchTermStream = new Subject(); - search(term:string) { this.searchTermStream.next(term); } + search(term: string) { this.searchTermStream.next(term); } // #enddocregion subject // #docregion observable-operators - items:Observable = this.searchTermStream + items: Observable = this.searchTermStream .debounceTime(300) .distinctUntilChanged() - .switchMap((term:string) => this.wikipediaService.search(term)); + .switchMap((term: string) => this.wikipediaService.search(term)); // #enddocregion observable-operators } diff --git a/public/docs/_examples/server-communication/ts/app/wiki/wiki.component.ts b/public/docs/_examples/server-communication/ts/app/wiki/wiki.component.ts index 5a764cbc52..63a0bc5f81 100644 --- a/public/docs/_examples/server-communication/ts/app/wiki/wiki.component.ts +++ b/public/docs/_examples/server-communication/ts/app/wiki/wiki.component.ts @@ -17,7 +17,7 @@ import { WikipediaService } from './wikipedia.service';
  • {{item}}
  • `, - providers:[JSONP_PROVIDERS, WikipediaService] + providers: [JSONP_PROVIDERS, WikipediaService] }) export class WikiComponent { diff --git a/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.ts b/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.ts index 3333c29cfb..8bc5747e43 100644 --- a/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.ts +++ b/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.ts @@ -11,7 +11,7 @@ export class WikipediaService { let wikiUrl = 'http://en.wikipedia.org/w/api.php'; // #docregion search-parameters - var params = new URLSearchParams(); + let params = new URLSearchParams(); params.set('search', term); // the user's search value params.set('action', 'opensearch'); params.set('format', 'json'); diff --git a/public/docs/ts/latest/guide/server-communication.jade b/public/docs/ts/latest/guide/server-communication.jade index a009dadedc..f630ac1d07 100644 --- a/public/docs/ts/latest/guide/server-communication.jade +++ b/public/docs/ts/latest/guide/server-communication.jade @@ -60,6 +60,7 @@ figure.image-display :marked Here is the `TohComponent` shell: +makeExample('server-communication/ts/app/toh/toh.component.ts', '', 'app/toh/toh.component.ts') + block http-providers :marked As usual, we import the symbols we need. The newcomer is `HTTP_PROVIDERS`, @@ -191,18 +192,26 @@ block rxjs We should include only those features that we actually need. Accordingly, Angular exposes a stripped down version of `Observable` in the `rxjs/Observable` module, - a version that lacks almost all operators including the ones we'd like to use here + a version that lacks most of the operators including some we'd like to use here such as the `map` method we called above in `getHeroes`. It's up to us to add the operators we need. - We could add each operator, one-by-one, until we had a custom *Observable* implementation tuned - precisely to our requirements. - - That would be a distraction today. We're learning HTTP, not counting bytes. - So we'll make it easy on ourselves and enrich *Observable* with the full set of operators. - It only takes one `import` statement. - It's best to add that statement early when we're bootstrapping the application. - : + + We could add _every_ RxJS operators with a single import statement. + While that is the easiest thing to do, we'd pay a penalty in extended launch time and application size + because the full library is so big. We only use a few operators in our app. + + Instead, we'll import each operator, one-by-one, until we have a custom *Observable* implementation tuned + precisely to our requirements. We'll put the `import` statements in one `app/add-rxjs-operators.ts` file. + +makeExample('server-communication/ts/app/add-rxjs-operators.ts', null, 'app/add-rxjs-operators.ts')(format=".") + :marked + If we forget an operator, the compiler will warn that it's missing and we'll update this file. + .l-sub-section + :marked + We don't need _all_ of these particular operators in the `HeroService` — just `map` and `catch`. + We'll need the others later, in a *Wiki* example [below](#more-observables). + :marked + Finally, we import `add-rxjs-operator`_itself_ in our `main.ts`: +makeExample('server-communication/ts/app/main.ts', 'import-rxjs', 'app/main.ts (import rxjs)')(format=".") a#extract-data @@ -212,31 +221,8 @@ a#extract-data +makeExample('server-communication/ts/app/toh/hero.service.ts', 'extract-data', 'app/toh/hero.service.ts (excerpt)')(format=".") :marked The `response` object does not hold our data in a form we can use directly. - To make it useful in our application we must - * check the response status, - * parse the response data into a JSON object + To make it useful in our application we must parse the response data into a JSON object -+ifDocsFor('ts') - .alert.is-important - :marked - *Beta alert*: error status interception and parsing may be absorbed within `http` when Angular is released. - -:marked - #### Non-success status codes - A status code outside the 200-299 range denotes an error from the _application point of view_ - but it is not an error from the _HTTP point of view_. - For example, a `404 - Not Found` is a response like any other. - The request went out; a response came back; here it is, thank you very much. - We'd have an exception only if `#{_priv}http` failed to operate (e.g., it errored internally). - -block non-success-status-codes - :marked - Because a status code outside the 200-299 range _is an error_ from the application point of view, - we intercept it and throw, moving the observable chain to the error path. - - The `catch` operator that is next in the `getHeroes` observable chain will handle our thrown error. - -:marked #### Parse to JSON block parse-json :marked @@ -597,7 +583,7 @@ block wikipedia-jsonp+ +makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'observable-operators')(format='.') :marked 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)). + ([debounceTime](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/debounce.md)). Only changed search values make it through to the service ([distinctUntilChanged](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/distinctuntilchanged.md)). @@ -611,6 +597,10 @@ block wikipedia-jsonp+ and delivers to subscribers only the most recent search results. The displayed list of search results stays in sync with the user's sequence of search terms. + .l-sub-section + :marked + We added the `debounceTime`, `distinctUntilChanged`, and `switchMap` operators to the RxJS `Observable` class + in `add-rxjs-operators` as [described above](#rxjs) a#in-mem-web-api .l-main-section