docs(toh-6/dart): getHero makes HTTP get-by-id (#2936)

Dart follow-up to #2906
This commit is contained in:
Patrice Chalin 2016-12-06 15:28:34 -08:00 committed by Kathy Walrath
parent bc416b8e0f
commit 499d4b3c88
4 changed files with 51 additions and 21 deletions

View File

@ -15,7 +15,7 @@ class HeroService {
static final _headers = {'Content-Type': 'application/json'}; static final _headers = {'Content-Type': 'application/json'};
// #enddocregion update // #enddocregion update
// #docregion getHeroes // #docregion getHeroes
static const _heroesUrl = 'app/heroes'; // URL to web API static const _heroesUrl = 'api/heroes'; // URL to web API
final Client _http; final Client _http;
@ -46,8 +46,16 @@ class HeroService {
} }
// #enddocregion handleError, getHeroes // #enddocregion handleError, getHeroes
Future<Hero> getHero(int id) async => // #docregion getHero
(await getHeroes()).firstWhere((hero) => hero.id == id); Future<Hero> getHero(int id) async {
try {
final response = await _http.get('$_heroesUrl/$id');
return new Hero.fromJson(_extractData(response));
} catch (e) {
throw _handleError(e);
}
}
// #enddocregion getHero
// #docregion create // #docregion create
Future<Hero> create(String name) async { Future<Hero> create(String name) async {
@ -64,7 +72,7 @@ class HeroService {
Future<Hero> update(Hero hero) async { Future<Hero> update(Hero hero) async {
try { try {
var url = '$_heroesUrl/${hero.id}'; final url = '$_heroesUrl/${hero.id}';
final response = final response =
await _http.put(url, headers: _headers, body: JSON.encode(hero)); await _http.put(url, headers: _headers, body: JSON.encode(hero));
return new Hero.fromJson(_extractData(response)); return new Hero.fromJson(_extractData(response));
@ -77,7 +85,7 @@ class HeroService {
// #docregion delete // #docregion delete
Future<Null> delete(int id) async { Future<Null> delete(int id) async {
try { try {
var url = '$_heroesUrl/$id'; final url = '$_heroesUrl/$id';
await _http.delete(url, headers: _headers); await _http.delete(url, headers: _headers);
} catch (e) { } catch (e) {
throw _handleError(e); throw _handleError(e);

View File

@ -31,9 +31,14 @@ class InMemoryDataService extends MockClient {
var data; var data;
switch (request.method) { switch (request.method) {
case 'GET': case 'GET':
String prefix = request.url.queryParameters['name'] ?? ''; final id = int.parse(request.url.pathSegments.last, onError: (_) => null);
final regExp = new RegExp(prefix, caseSensitive: false); if (id != null) {
data = _heroesDb.where((hero) => hero.name.contains(regExp)).toList(); data = _heroesDb.firstWhere((hero) => hero.id == id); // throws if no match
} else {
String prefix = request.url.queryParameters['name'] ?? '';
final regExp = new RegExp(prefix, caseSensitive: false);
data = _heroesDb.where((hero) => hero.name.contains(regExp)).toList();
}
break; break;
// #enddocregion init-disabled // #enddocregion init-disabled
case 'POST': case 'POST':

View File

@ -212,12 +212,32 @@ block get-heroes-details
We've also decided to return a user friendly form of the error to We've also decided to return a user friendly form of the error to
the caller in a !{rejected_promise} so that the caller can display a proper error message to the user. the caller in a !{rejected_promise} so that the caller can display a proper error message to the user.
### Unchanged `getHeroes` API ### Get hero by id
The `HeroDetailComponent` asks the `HeroService` to fetch a single hero to edit.
Although we made significant *internal* changes to `getHeroes()`, the public signature did not change. The `HeroService` currently fetches all heroes and then finds the desired hero
We still return a !{_Promise}. We won't have to update any of the components that call `getHeroes()`. by filtering for the one with the matching `id`.
That's fine in a simulation. It's wasteful to ask a real server for _all_ heroes when we only want one.
Most web APIs support a _get-by-id_ request in the form `api/hero/:id` (e.g., `api/hero/11`).
Our stakeholders are thrilled with the added flexibility from the API integration. Update the `HeroService.getHero` method to make a _get-by-id_ request,
applying what we just learned to write `getHeroes`:
+makeExcerpt('app/hero.service.ts', 'getHero', '')
:marked
It's almost the same as `getHeroes`.
The URL identifies _which_ hero the server should update by encoding the hero id into the URL
to match the `api/hero/:id` pattern.
We also adjust to the fact that the `data` in the response is a single hero object rather than !{_an} !{_array}.
### Unchanged _getHeroes_ API
Although we made significant *internal* changes to `getHeroes()` and `getHero()`,
the public signatures did not change.
We still return a !{_Promise} from both methods.
We won't have to update any of the components that call them.
Our stakeholders are thrilled with the web API integration so far.
Now they want the ability to create and delete heroes. Now they want the ability to create and delete heroes.
Let's see first what happens when we try to update a hero's details. Let's see first what happens when we try to update a hero's details.
@ -230,15 +250,12 @@ block get-heroes-details
it. As we type, the hero name is updated in the view heading. it. As we type, the hero name is updated in the view heading.
But when we hit the `Back` button, the changes are lost! But when we hit the `Back` button, the changes are lost!
.l-sub-section Updates weren't lost before. What changed?
:marked When the app used a list of mock heroes, updates were applied directly to the
Updates weren't lost before, what's happening? hero objects within the single, app-wide, shared list. Now that we are fetching data
When the app used a list of mock heroes, changes were made directly to the from a server, if we want changes to persist, we'll need to write them back to
hero objects in the single, app-wide shared list. Now that we are fetching data the server.
from a server, if we want changes to persist, we'll need to write them back to
the server.
:marked
### Save hero details ### Save hero details
Let's ensure that edits to a hero's name aren't lost. Start by adding, Let's ensure that edits to a hero's name aren't lost. Start by adding,

View File

@ -228,7 +228,7 @@ block get-heroes-details
The URL identifies _which_ hero the server should update by encoding the hero id into the URL The URL identifies _which_ hero the server should update by encoding the hero id into the URL
to match the `api/hero/:id` pattern. to match the `api/hero/:id` pattern.
We also adjust to the fact that the `data` in the response is a single hero object rather than array. We also adjust to the fact that the `data` in the response is a single hero object rather than !{_an} !{_array}.
### Unchanged _getHeroes_ API ### Unchanged _getHeroes_ API