docs: update text around changed obs examples (#22920)

PR Close #22920
This commit is contained in:
Judy Bogart 2018-03-21 16:26:50 -07:00 committed by Alex Rickabaugh
parent 28058b784b
commit 9f7bd8f618
7 changed files with 44 additions and 56 deletions

View File

@ -313,7 +313,6 @@ It takes two more parameters:
1. `httpOptions` - the method options which, in this case, [specify required headers](#adding-headers).
Of course it catches errors in much the same manner [described above](#error-details).
It also _taps_ the returned observable in order to log the successful POST.
The `HeroesComponent` initiates the actual POST operation by subscribing to
the `Observable` returned by this service method.
@ -347,18 +346,14 @@ the `Observable` returned by this service method.
title="app/heroes/heroes.component.ts (deleteHero)" linenums="false">
</code-example>
The component isn't expecting a result from the delete operation, so it subscribes without a callback. Even though you are not using the result, you still have to subscribe. Calling the `subscribe()` method _executes_ the observable, which is what initiates the DELETE request.
<div class="alert is-important">
You must call _subscribe()_ or nothing happens!
You must call _subscribe()_ or nothing happens. Just calling `HeroService.deleteHero()` **does not initiate the DELETE request.**
</div>
The component isn't expecting a result from the delete operation and
subscribes without a callback.
The bare `.subscribe()` _seems_ pointless.
In fact, it is essential.
Merely calling `HeroService.deleteHero()` **does not initiate the DELETE request.**
<code-example
path="http/src/app/heroes/heroes.component.ts"
@ -366,7 +361,7 @@ Merely calling `HeroService.deleteHero()` **does not initiate the DELETE request
</code-example>
{@a always-subscribe}
### Always _subscribe_!
**Always _subscribe_!**
An `HttpClient` method does not begin its HTTP request until you call `subscribe()` on the observable returned by that method. This is true for _all_ `HttpClient` _methods_.
@ -378,8 +373,7 @@ The [`AsyncPipe`](api/common/AsyncPipe) subscribes (and unsubscribes) for you au
All observables returned from `HttpClient` methods are _cold_ by design.
Execution of the HTTP request is _deferred_, allowing you to extend the
observable with additional operations such as `tap` and `catchError`
before anything actually happens.
observable with additional operations such as `tap` and `catchError` before anything actually happens.
Calling `subscribe(...)` triggers execution of the observable and causes
`HttpClient` to compose and send the HTTP request to the server.
@ -417,7 +411,7 @@ in order to initiate the request.
## Advanced usage
The above sections detail how to use the basic HTTP functionality in `@angular/common/http`, but sometimes you need to do more than make simple requests and get data back.
We have discussed the basic HTTP functionality in `@angular/common/http`, but sometimes you need to do more than make simple requests and get data back.
### Configuring the request
@ -454,7 +448,7 @@ Here is a `searchHeroes` method that queries for heroes whose names contain the
region="searchHeroes" linenums="false">
</code-example>
If there is a search term, the code constructs an options object with an HTML URL encoded search parameter. If the term were "foo", the GET request URL would be `api/heroes/?name=foo`.
If there is a search term, the code constructs an options object with an HTML URL-encoded search parameter. If the term were "foo", the GET request URL would be `api/heroes/?name=foo`.
The `HttpParms` are immutable so you'll have to use the `set()` method to update the options.
@ -463,7 +457,7 @@ The `HttpParms` are immutable so you'll have to use the `set()` method to update
The sample includes an _npm package search_ feature.
When the user enters a name in a search-box, the `PackageSearchComponent` sends
a search request for a package with that name to the NPM web api.
a search request for a package with that name to the NPM web API.
Here's a pertinent excerpt from the template:
@ -486,7 +480,7 @@ That's easy to implement with RxJS operators, as shown in this excerpt.
</code-example>
The `searchText$` is the sequence of search-box values coming from the user.
It's defined as an RxJS `Subject`, which means it is an `Observable`
It's defined as an RxJS `Subject`, which means it is a multicasting `Observable`
that can also produce values for itself by calling `next(value)`,
as happens in the `search()` method.
@ -820,7 +814,7 @@ Some folks describe it as a "_one and done_" observable.
But an interceptor can change this to an _observable_ that emits more than once.
A revised version of the `CachingInterceptor` optionally returns an _observable_ that
immediately emits the cached response, sends the request to the npm web api anyway,
immediately emits the cached response, sends the request to the NPM web API anyway,
and emits again later with the updated search results.
<code-example

View File

@ -940,8 +940,7 @@ with that hero's data values.
A refresh button clears the hero list and the current selected hero before refetching the heroes.
Notice that `hero-list.component.ts` imports `Observable` and `finally` while `hero.service.ts` imports `Observable`, `of`,
and `delay` from `rxjs`.
Notice that `hero-list.component.ts` imports `Observable` and the `finally` operator, while `hero.service.ts` imports `Observable`, `of` and the `delay` operator from `rxjs`.
The remaining `HeroListComponent` and `HeroService` implementation details are beyond the scope of this tutorial.
However, the techniques involved are covered elsewhere in the documentation, including the _Tour of Heroes_

View File

@ -1619,8 +1619,7 @@ They are distributed across two modules, `AppRoutingModule` and `HeroesRoutingMo
Each routing module augments the route configuration _in the order of import_.
If you list `AppRoutingModule` first, the wildcard route will be registered
_before_ the hero routes.
The wildcard route &mdash; which matches _every_ URL &mdash;
will intercept the attempt to navigate to a hero route.
The wildcard route&mdash;which matches _every_ URL&mdash;will intercept the attempt to navigate to a hero route.
<div class="l-sub-section">
@ -3149,7 +3148,7 @@ Here's a demo `AuthService`:
Although it doesn't actually log in, it has what you need for this discussion.
It has an `isLoggedIn` flag to tell you whether the user is authenticated.
Its `login` method simulates an API call to an external service by returning an
Observable that resolves successfully after a short pause.
observable that resolves successfully after a short pause.
The `redirectUrl` property will store the attempted URL so you can navigate to it after authenticating.
Revise the `AuthGuard` to call it.
@ -3459,13 +3458,11 @@ Be explicit. Implement the `Resolve` interface with a type of `Crisis`.
Inject the `CrisisService` and `Router` and implement the `resolve()` method.
That method could return a `Promise`, an `Observable`, or a synchronous return value.
The `CrisisService.getCrisis` method returns an Observable.
Return that observable to prevent the route from loading until the data is fetched.
The `Router` guards require an Observable to `complete`, meaning it has emitted all
The `CrisisService.getCrisis` method returns an observable, in order to prevent the route from loading until the data is fetched.
The `Router` guards require an observable to `complete`, meaning it has emitted all
of its values. You use the `take` operator with an argument of `1` to ensure that the
Observable completes after retrieving the first value from the Observable returned by the
`getCrisis` method.
If it doesn't return a valid `Crisis`, navigate the user back to the `CrisisListComponent`,
observable completes after retrieving the first value from the observable returned by the
`getCrisis` method. If it doesn't return a valid `Crisis`, navigate the user back to the `CrisisListComponent`,
canceling the previous in-flight navigation to the `CrisisDetailComponent`.
Import this resolver in the `crisis-center-routing.module.ts`
@ -3502,8 +3499,8 @@ The router looks for that method and calls it if found.
Don't worry about all the ways that the user could navigate away.
That's the router's job. Write this class and let the router take it from there.
1. The Observable provided to the Router _must_ complete.
If the Observable does not complete, the navigation will not continue.
1. The observable provided to the Router _must_ complete.
If the observable does not complete, the navigation will not continue.
The relevant *Crisis Center* code for this milestone follows.

View File

@ -262,13 +262,12 @@ test any service with a dependency.
<div class="alert is-important">
The `HeroService` methods return _Observables_.
_Subscribe_ to the method observable to (a) cause it to execute and (b)
The `HeroService` methods return `Observables`. You must
_subscribe_ to an observable to (a) cause it to execute and (b)
assert that the method succeeds or fails.
The `subscribe()` method takes a success and fail callback.
The `subscribe()` method takes a success (`next`) and fail (`error`) callback.
Make sure you provide _both_ callbacks so that you capture errors.
Neglecting to do so produces an asynchronous uncaught observable error that
the test runner will likely attribute to a completely different test.
@ -1024,9 +1023,9 @@ Focus on the spy.
region="spy">
</code-example>
The spy is designed such that any call to `getQuote` receives an Observable with a test quote.
The spy is designed such that any call to `getQuote` receives an observable with a test quote.
Unlike the real `getQuote()` method, this spy bypasses the server
and returns a synchronous Observable whose value is available immediately.
and returns a synchronous observable whose value is available immediately.
You can write many useful tests with this spy, even though its `Observable` is synchronous.
@ -1114,14 +1113,14 @@ Or you can copy this one from the sample code.
This helper's observable emits the `data` value in the next turn of the JavaScript engine.
[RxJS `defer()`](http://reactivex.io/documentation/operators/defer.html) returns an observable.
The [RxJS `defer()` operator](http://reactivex.io/documentation/operators/defer.html) returns an observable.
It takes a factory function that returns either a promise or an observable.
When something subscribes to _defer_'s observable,
it adds the subscriber to a new observable created with that factory.
RxJS `defer()` transform the `Promise.resolve()` into a new observable that,
The `defer()` operator transforms the `Promise.resolve()` into a new observable that,
like `HttpClient`, emits once and completes.
Subscribers will be unsubscribed after they receive the data value.
Subscribers are unsubscribed after they receive the data value.
There's a similar helper for producing an async error.
@ -1689,9 +1688,8 @@ Here's the `HeroDetailComponent` constructor:
The `HeroDetail` component needs the `id` parameter so it can fetch
the corresponding hero via the `HeroDetailService`.
The component has to get the `id` from the `ActivatedRoute.paramMap` property
which is an _Observable_.
which is an `Observable`.
It can't just reference the `id` property of the `ActivatedRoute.paramMap`.
The component has to _subscribe_ to the `ActivatedRoute.paramMap` observable and be prepared

View File

@ -1342,7 +1342,7 @@ and the other loads the details of a specified phone:
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" region="fullclass" title="app/core/phone/phone.service.ts">
</code-example>
The methods now return Observables of type `PhoneData` and `PhoneData[]`. This is
The methods now return observables of type `PhoneData` and `PhoneData[]`. This is
a type you don't have yet. Add a simple interface for it:
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" region="phonedata-interface" title="app/core/phone/phone.service.ts (interface)" linenums="false">
@ -1385,14 +1385,14 @@ it's really an instance of the `Phone` class and you annotate its type according
Now there are two AngularJS components using an Angular service!
The components don't need to be aware of this, though the fact that the
service returns Observables and not Promises is a bit of a giveaway.
service returns observables and not promises is a bit of a giveaway.
In any case, what you've achieved is a migration of a service to Angular
without having to yet migrate the components that use it.
<div class="alert is-helpful">
You could use the `toPromise` method of `Observable` to turn those
Observables into Promises in the service. In many cases that reduce
observables into promises in the service. In many cases that reduce
the number of changes to the component controllers.
</div>

View File

@ -446,7 +446,7 @@ Here are the code files discussed on this page and your app should look like thi
* You used [Angular Dependency Injection](guide/dependency-injection) to inject it into a component.
* You gave the `HeroService` _get data_ method an asynchronous signature.
* You discovered `Observable` and the RxJS _Observable_ library.
* You used RxJS `of()` to return an _Observable_ of mock heroes (`Observable<Hero[]>`).
* You used RxJS `of()` to return an observable of mock heroes (`Observable<Hero[]>`).
* The component's `ngOnInit` lifecycle hook calls the `HeroService` method, not the constructor.
* You created a `MessageService` for loosely-coupled communication between classes.
* The `HeroService` injected into a component is created with another injected service,

View File

@ -145,8 +145,8 @@ All `HttpClient` methods return an RxJS `Observable` of something.
HTTP is a request/response protocol.
You make a request, it returns a single response.
In general, an `Observable` _can_ return multiple values over time.
An `Observable` from `HttpClient` always emits a single value and then completes, never to emit again.
In general, an observable _can_ return multiple values over time.
An observable from `HttpClient` always emits a single value and then completes, never to emit again.
This particular `HttpClient.get` call returns an `Observable<Hero[]>`, literally "_an observable of hero arrays_". In practice, it will only return a single hero array.
@ -513,8 +513,8 @@ The `searchTerms` becomes an `Observable` emitting a steady stream of search ter
Passing a new search term directly to the `searchHeroes()` after every user keystroke would create an excessive amount of HTTP requests,
taxing server resources and burning through the cellular network data plan.
Instead, the `ngOnInit()` method pipes the `searchTerms` _observable_ through a sequence of RxJS operators that reduce the number of calls to the `searchHeroes()`,
ultimately returning an _observable_ of timely hero search results (each a `Hero[]`).
Instead, the `ngOnInit()` method pipes the `searchTerms` observable through a sequence of RxJS operators that reduce the number of calls to the `searchHeroes()`,
ultimately returning an observable of timely hero search results (each a `Hero[]`).
Here's the code.
@ -529,7 +529,7 @@ Here's the code.
before passing along the latest string. You'll never make requests more frequently than 300ms.
* `distinctUntilChanged` ensures that a request is sent only if the filter text changed.
* `distinctUntilChanged()` ensures that a request is sent only if the filter text changed.
* `switchMap()` calls the search service for each search term that makes it through `debounce` and `distinctUntilChanged`.
@ -648,7 +648,7 @@ You're at the end of your journey, and you've accomplished a lot.
* You extended `HeroService` to support `post()`, `put()`, and `delete()` methods.
* You updated the components to allow adding, editing, and deleting of heroes.
* You configured an in-memory web API.
* You learned how to use Observables.
* You learned how to use observables.
This concludes the "Tour of Heroes" tutorial.
You're ready to learn more about Angular development in the fundamentals section,