docs(pipes): improve FetchJsonPipe discussion (#2923)
This commit is contained in:
parent
977492a290
commit
93c78dae10
@ -1,6 +1,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
import { Http } from '@angular/http';
|
import { Http } from '@angular/http';
|
||||||
|
import './rxjs-extensions';
|
||||||
|
|
||||||
// #docregion pipe-metadata
|
// #docregion pipe-metadata
|
||||||
@Pipe({
|
@Pipe({
|
||||||
@ -9,20 +10,20 @@ import { Http } from '@angular/http';
|
|||||||
})
|
})
|
||||||
// #enddocregion pipe-metadata
|
// #enddocregion pipe-metadata
|
||||||
export class FetchJsonPipe implements PipeTransform {
|
export class FetchJsonPipe implements PipeTransform {
|
||||||
private fetchedJson: any = null;
|
private cachedData: any = null;
|
||||||
private prevUrl = '';
|
private cachedUrl = '';
|
||||||
|
|
||||||
constructor(private _http: Http) { }
|
constructor(private http: Http) { }
|
||||||
|
|
||||||
transform(url: string): any {
|
transform(url: string): any {
|
||||||
if (url !== this.prevUrl) {
|
if (url !== this.cachedUrl) {
|
||||||
this.prevUrl = url;
|
this.cachedData = null;
|
||||||
this.fetchedJson = null;
|
this.cachedUrl = url;
|
||||||
this._http.get(url)
|
this.http.get(url)
|
||||||
.map( result => result.json() )
|
.map( result => result.json() )
|
||||||
.subscribe( result => this.fetchedJson = result );
|
.subscribe( result => this.cachedData = result );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.fetchedJson;
|
return this.cachedData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import './rxjs-extensions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-message',
|
selector: 'hero-message',
|
||||||
|
@ -3,7 +3,6 @@ import { Component } from '@angular/core';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list',
|
selector: 'hero-list',
|
||||||
// #docregion template
|
|
||||||
template: `
|
template: `
|
||||||
<h2>Heroes from JSON File</h2>
|
<h2>Heroes from JSON File</h2>
|
||||||
|
|
||||||
@ -12,9 +11,7 @@ import { Component } from '@angular/core';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Heroes as JSON:
|
<p>Heroes as JSON:
|
||||||
{{'heroes.json' | fetch | json}}
|
{{'heroes.json' | fetch | json}}
|
||||||
</p>
|
</p>`
|
||||||
`
|
|
||||||
// #enddocregion template
|
|
||||||
})
|
})
|
||||||
export class HeroListComponent { }
|
export class HeroListComponent { }
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
import 'rxjs/Rx';
|
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||||
|
5
public/docs/_examples/pipes/ts/app/rxjs-extensions.ts
Normal file
5
public/docs/_examples/pipes/ts/app/rxjs-extensions.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Extensions to RxJS used in this app.
|
||||||
|
import 'rxjs/add/observable/interval';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import 'rxjs/add/operator/take';
|
@ -361,44 +361,42 @@ h3#async-pipe The impure #[i AsyncPipe]
|
|||||||
The component doesn't have to subscribe to the async data source,
|
The component doesn't have to subscribe to the async data source,
|
||||||
it doesn't extract the resolved values and expose them for binding,
|
it doesn't extract the resolved values and expose them for binding,
|
||||||
and the component doesn't have to unsubscribe when it is destroyed
|
and the component doesn't have to unsubscribe when it is destroyed
|
||||||
(a potent source of memory leaks).
|
(a potential source of memory leaks).
|
||||||
|
|
||||||
### An impure caching pipe
|
### An impure caching pipe
|
||||||
|
|
||||||
Let's write one more impure pipe, a pipe that makes an HTTP request to the server.
|
Let's write one more impure pipe, a pipe that makes an HTTP request.
|
||||||
Normally, that's a horrible idea.
|
|
||||||
It's probably a horrible idea no matter what we do.
|
Remember that impure pipes are called every few milliseconds.
|
||||||
We're forging ahead anyway to make a point.
|
|
||||||
Remember that impure pipes are called every few microseconds.
|
|
||||||
If we're not careful, this pipe will punish the server with requests.
|
If we're not careful, this pipe will punish the server with requests.
|
||||||
|
|
||||||
We are careful. Our pipe only makes a server call if the request URL has changed.
|
We are careful.
|
||||||
It caches the request URL and waits for a result which it also caches when it arrives.
|
The pipe only calls the server when the request URL changes and it caches the server response.
|
||||||
The pipe returns the cached result (which is null while a request is in flight)
|
Here's the code, which uses the [Angular http](server-communication.html) client to retrieve data:
|
||||||
after every Angular call and only contacts the server as necessary.
|
|
||||||
|
|
||||||
Here's the code, which uses the [Angular http](server-communication.html) facility
|
|
||||||
to retrieve a `heroes.json` file:
|
|
||||||
|
|
||||||
+makeExample('pipes/ts/app/fetch-json.pipe.ts', null, 'app/fetch-json.pipe.ts')
|
+makeExample('pipes/ts/app/fetch-json.pipe.ts', null, 'app/fetch-json.pipe.ts')
|
||||||
:marked
|
:marked
|
||||||
Then we demonstrate it in a harness component whose template defines two bindings to this pipe.
|
Then we demonstrate it in a harness component whose template defines two bindings to this pipe,
|
||||||
+makeExample('pipes/ts/app/hero-list.component.ts', 'template', 'app/hero-list.component.ts (template)')
|
both requesting the heroes from the `heroes.json` file.
|
||||||
:marked
|
|
||||||
Despite the two bindings and what we know to be frequent pipe calls,
|
|
||||||
the nework tab in the browser developer tools confirms that there is only one request for the file.
|
|
||||||
|
|
||||||
|
+makeExample('pipes/ts/app/hero-list.component.ts', null, 'app/hero-list.component.ts')
|
||||||
|
:marked
|
||||||
The component renders like this:
|
The component renders like this:
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/pipes/hero-list.png' alt="Hero List")
|
img(src='/resources/images/devguide/pipes/hero-list.png' alt="Hero List")
|
||||||
|
|
||||||
|
:marked
|
||||||
|
A breakpoint on the pipe's request for data shows that
|
||||||
|
* each binding gets its own pipe instance
|
||||||
|
* each pipe instance caches its own url and data
|
||||||
|
* each pipe instance only calls the server once
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
### *JsonPipe*
|
### *JsonPipe*
|
||||||
|
|
||||||
The second binding involving the `FetchPipe` uses more pipe chaining.
|
The second `fetch` pipe binding above demonstrates more pipe chaining.
|
||||||
We take the same fetched results displayed in the first binding
|
It displays the same hero data in JSON format by chaining through to the built-in `JsonPipe`.
|
||||||
and display them again, this time in JSON format by chaining through to the built-in `JsonPipe`.
|
|
||||||
|
|
||||||
.callout.is-helpful
|
.callout.is-helpful
|
||||||
header Debugging with the json pipe
|
header Debugging with the json pipe
|
||||||
@ -407,11 +405,6 @@ figure.image-display
|
|||||||
provides an easy way to diagnosis a mysteriously failing data binding or
|
provides an easy way to diagnosis a mysteriously failing data binding or
|
||||||
inspect an object for future binding.
|
inspect an object for future binding.
|
||||||
|
|
||||||
:marked
|
|
||||||
Here's the complete component implementation:
|
|
||||||
|
|
||||||
+makeExample('pipes/ts/app/hero-list.component.ts', null, 'app/hero-list.component.ts')
|
|
||||||
|
|
||||||
a(id="pure-pipe-pure-fn")
|
a(id="pure-pipe-pure-fn")
|
||||||
:marked
|
:marked
|
||||||
### Pure pipes and pure functions
|
### Pure pipes and pure functions
|
||||||
|
@ -365,40 +365,38 @@ h3#async-pipe The impure #[i AsyncPipe]
|
|||||||
|
|
||||||
### An impure caching pipe
|
### An impure caching pipe
|
||||||
|
|
||||||
Let's write one more impure pipe, a pipe that makes an HTTP request to the server.
|
Let's write one more impure pipe, a pipe that makes an HTTP request.
|
||||||
Normally, that's a horrible idea.
|
|
||||||
It's probably a horrible idea no matter what we do.
|
Remember that impure pipes are called every few milliseconds.
|
||||||
We're forging ahead anyway to make a point.
|
|
||||||
Remember that impure pipes are called every few microseconds.
|
|
||||||
If we're not careful, this pipe will punish the server with requests.
|
If we're not careful, this pipe will punish the server with requests.
|
||||||
|
|
||||||
We are careful. Our pipe only makes a server call if the request URL has changed.
|
We are careful.
|
||||||
It caches the request URL and waits for a result which it also caches when it arrives.
|
The pipe only calls the server when the request URL changes and it caches the server response.
|
||||||
The pipe returns the cached result (which is null while a request is in flight)
|
Here's the code, which uses the [Angular http](server-communication.html) client to retrieve data:
|
||||||
after every Angular call and only contacts the server as necessary.
|
|
||||||
|
|
||||||
Here's the code, which uses the [Angular http](server-communication.html) facility
|
|
||||||
to retrieve a `heroes.json` file:
|
|
||||||
|
|
||||||
+makeExample('pipes/ts/app/fetch-json.pipe.ts', null, 'app/fetch-json.pipe.ts')
|
+makeExample('pipes/ts/app/fetch-json.pipe.ts', null, 'app/fetch-json.pipe.ts')
|
||||||
:marked
|
:marked
|
||||||
Then we demonstrate it in a harness component whose template defines two bindings to this pipe.
|
Then we demonstrate it in a harness component whose template defines two bindings to this pipe,
|
||||||
+makeExample('pipes/ts/app/hero-list.component.ts', 'template', 'app/hero-list.component.ts (template)')
|
both requesting the heroes from the `heroes.json` file.
|
||||||
:marked
|
|
||||||
Despite the two bindings and what we know to be frequent pipe calls,
|
|
||||||
the nework tab in the browser developer tools confirms that there is only one request for the file.
|
|
||||||
|
|
||||||
|
+makeExample('pipes/ts/app/hero-list.component.ts', null, 'app/hero-list.component.ts')
|
||||||
|
:marked
|
||||||
The component renders like this:
|
The component renders like this:
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/pipes/hero-list.png' alt="Hero List")
|
img(src='/resources/images/devguide/pipes/hero-list.png' alt="Hero List")
|
||||||
|
|
||||||
|
:marked
|
||||||
|
A breakpoint on the pipe's request for data shows that
|
||||||
|
* each binding gets its own pipe instance
|
||||||
|
* each pipe instance caches its own url and data
|
||||||
|
* each pipe instance only calls the server once
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
### *JsonPipe*
|
### *JsonPipe*
|
||||||
|
|
||||||
The second binding involving the `FetchPipe` uses more pipe chaining.
|
The second `fetch` pipe binding above demonstrates more pipe chaining.
|
||||||
We take the same fetched results displayed in the first binding
|
It displays the same hero data in JSON format by chaining through to the built-in `JsonPipe`.
|
||||||
and display them again, this time in JSON format by chaining through to the built-in `JsonPipe`.
|
|
||||||
|
|
||||||
.callout.is-helpful
|
.callout.is-helpful
|
||||||
header Debugging with the json pipe
|
header Debugging with the json pipe
|
||||||
@ -407,11 +405,6 @@ figure.image-display
|
|||||||
provides an easy way to diagnosis a mysteriously failing data binding or
|
provides an easy way to diagnosis a mysteriously failing data binding or
|
||||||
inspect an object for future binding.
|
inspect an object for future binding.
|
||||||
|
|
||||||
:marked
|
|
||||||
Here's the complete component implementation:
|
|
||||||
|
|
||||||
+makeExample('pipes/ts/app/hero-list.component.ts', null, 'app/hero-list.component.ts')
|
|
||||||
|
|
||||||
a(id="pure-pipe-pure-fn")
|
a(id="pure-pipe-pure-fn")
|
||||||
:marked
|
:marked
|
||||||
### Pure pipes and pure functions
|
### Pure pipes and pure functions
|
||||||
|
Loading…
x
Reference in New Issue
Block a user