720 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			720 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
block includes
 | 
						|
  include ../_util-fns
 | 
						|
  - var _Http = 'Http'; // Angular `Http` library name.
 | 
						|
  - var _Angular_Http = 'Angular <code>Http</code>'
 | 
						|
  - var _Angular_http_library = 'Angular HTTP library'
 | 
						|
 | 
						|
:marked
 | 
						|
  [HTTP](https://tools.ietf.org/html/rfc2616) is the primary protocol for browser/server communication.
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    The [`WebSocket`](https://tools.ietf.org/html/rfc6455) protocol is another important communication technology;
 | 
						|
    it isn't covered in this page.
 | 
						|
:marked
 | 
						|
  Modern browsers support two HTTP-based APIs:
 | 
						|
  [XMLHttpRequest (XHR)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) and
 | 
						|
  [JSONP](https://en.wikipedia.org/wiki/JSONP). A few browsers also support
 | 
						|
  [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
 | 
						|
 | 
						|
  The !{_Angular_http_library} simplifies application programming with the **XHR** and **JSONP** APIs.
 | 
						|
  This page covers:
 | 
						|
 | 
						|
  - [The Tour of Heroes *HTTP* client demo](#http-client).
 | 
						|
  - [Fetch data with http.get](#fetch-data).
 | 
						|
  <li if-docs="ts"> [RxJS library](#rxjs).</li>
 | 
						|
  <li if-docs="ts"> [Enable RxJS operators](#enable-rxjs-operators).</li>
 | 
						|
  - [Process the response object](#extract-data).
 | 
						|
  - [Always handle errors](#error-handling).
 | 
						|
  - [Send data to the server](#update).
 | 
						|
  <li if-docs="ts"> [Fall back to promises](#promises).</li>
 | 
						|
  - [Cross-Origin Requests: Wikipedia example](#cors).
 | 
						|
    <ul if-docs="ts">
 | 
						|
      <li> [Search parameters](#search-parameters).</li>
 | 
						|
      <li> [More fun with observables](#more-observables).</li>
 | 
						|
    </ul>
 | 
						|
  - [Guarding against Cross-Site Request Forgery](#xsrf)
 | 
						|
  - [Appendix: Tour of Heroes in-memory server](#in-mem-web-api).
 | 
						|
 | 
						|
  A <live-example>live example</live-example> illustrates these topics.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  # Demos
 | 
						|
 | 
						|
  This page describes server communication with the help of the following demos:
 | 
						|
 | 
						|
block demos-list
 | 
						|
  :marked
 | 
						|
    - [The Tour of Heroes *HTTP* client demo](#http-client).
 | 
						|
    - [Fall back to !{_Promise}s](#promises).
 | 
						|
    - [Cross-Origin Requests: Wikipedia example](#cors).
 | 
						|
    - [More fun with observables](#more-observables).
 | 
						|
 | 
						|
:marked
 | 
						|
  The root `AppComponent` orchestrates these demos:
 | 
						|
+makeExample('server-communication/ts/app/app.component.ts', null, 'app/app.component.ts')
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  :marked
 | 
						|
    There is nothing remarkable here _except_ for the import of RxJS operators, which is
 | 
						|
    described [later](#rxjs).
 | 
						|
  +makeExample('server-communication/ts/app/app.component.ts', 'import-rxjs')(format='.')
 | 
						|
 | 
						|
.l-main-section#http-providers
 | 
						|
:marked
 | 
						|
  # Providing HTTP services
 | 
						|
 | 
						|
  First, configure the application to use server communication facilities.
 | 
						|
 | 
						|
  The !{_Angular_Http} client communicates with the server using a familiar HTTP request/response protocol.
 | 
						|
  The `!{_Http}` client is one of a family of services in the !{_Angular_http_library}.
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      When importing from the `@angular/http` module, SystemJS knows how to load services from
 | 
						|
      the !{_Angular_http_library}
 | 
						|
      because the `systemjs.config.js` file maps to that module name.
 | 
						|
 | 
						|
:marked
 | 
						|
  Before you can use the `!{_Http}` client, you need to register it as a service provider with the dependency injection system.
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Read about providers in the [Dependency Injection](dependency-injection.html) page.
 | 
						|
 | 
						|
:marked
 | 
						|
  Register providers by importing other NgModules to the root NgModule in `app.module.ts`.
 | 
						|
 | 
						|
+makeExample('server-communication/ts/app/app.module.1.ts', null, 'app/app.module.ts (v1)')(format='.')
 | 
						|
 | 
						|
block http-providers
 | 
						|
  :marked
 | 
						|
    Begin by importing the necessary members.
 | 
						|
    The newcomers are the `HttpModule` and the `JsonpModule` from the !{_Angular_http_library}. For more information about imports and related terminology, see the [MDN reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) on the `import` statement.
 | 
						|
 | 
						|
    To add these modules to the application, pass them to the `imports` array in the root `@NgModule`.
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    The `HttpModule` is necessary for making HTTP calls.
 | 
						|
    Though the JsonpModule isn't necessary for plain HTTP,
 | 
						|
    there is a JSONP demo later in this page.
 | 
						|
    Loading its module now saves time.
 | 
						|
.l-main-section#http-client
 | 
						|
:marked
 | 
						|
  # The Tour of Heroes HTTP client demo
 | 
						|
 | 
						|
  The first demo is a mini-version of the [tutorial](../tutorial)'s "Tour of Heroes" (ToH) application.
 | 
						|
  This version gets some heroes from the server, displays them in a list, lets the user add new heroes, and saves them to the server.
 | 
						|
  The app uses the !{_Angular_Http} client to communicate via `XMLHttpRequest (XHR)`.
 | 
						|
 | 
						|
  It works like this:
 | 
						|
figure.image-display
 | 
						|
  img(src='/resources/images/devguide/server-communication/http-toh.gif' alt="ToH mini app" width="250")
 | 
						|
:marked
 | 
						|
  This demo has a single component, the `HeroListComponent`.  Here's its template:
 | 
						|
+makeExample('server-communication/ts/app/toh/hero-list.component.html', null, 'app/toh/hero-list.component.html (template)')
 | 
						|
:marked
 | 
						|
  It presents the list of heroes with an `ngFor`.
 | 
						|
  Below the list is an input box and an *Add Hero* button where you can enter the names of new heroes
 | 
						|
  and add them to the database.
 | 
						|
  A [template reference variable](template-syntax.html#ref-vars), `newHeroName`, accesses the
 | 
						|
  value of the input box in the `(click)` event binding.
 | 
						|
  When the user clicks the button, that value passes to the component's `addHero` method and then
 | 
						|
  the event binding clears it to make it ready for a new hero name.
 | 
						|
 | 
						|
  Below the button is an area for an error message.
 | 
						|
 | 
						|
a#oninit
 | 
						|
a#HeroListComponent
 | 
						|
:marked
 | 
						|
  ## The *HeroListComponent* class
 | 
						|
  Here's the component class:
 | 
						|
+makeExample('server-communication/ts/app/toh/hero-list.component.ts','component', 'app/toh/hero-list.component.ts (class)')
 | 
						|
:marked
 | 
						|
  Angular [injects](dependency-injection.html) a `HeroService` into the constructor
 | 
						|
  and the component calls that service to fetch and save data.
 | 
						|
 | 
						|
  The component **does not talk directly to the !{_Angular_Http} client**.
 | 
						|
  The component doesn't know or care how it gets the data.
 | 
						|
  It delegates to the `HeroService`.
 | 
						|
 | 
						|
  This is a golden rule: **always delegate data access to a supporting service class**.
 | 
						|
 | 
						|
  Although _at runtime_ the component requests heroes immediately after creation,
 | 
						|
  you **don't** call the service's `get` method in the component's constructor.
 | 
						|
  Instead, call it inside the `ngOnInit` [lifecycle hook](lifecycle-hooks.html)
 | 
						|
  and rely on Angular to call `ngOnInit` when it instantiates this component.
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    This is a *best practice*.
 | 
						|
    Components are easier to test and debug when their constructors are simple, and all real work
 | 
						|
    (especially calling a remote server) is handled in a separate method.
 | 
						|
block getheroes-and-addhero
 | 
						|
  :marked
 | 
						|
    The service's `getHeroes()` and `addHero()` methods return an `Observable` of hero data that the !{_Angular_Http} client fetched from the server.
 | 
						|
 | 
						|
    Think of an `Observable` as a stream of events published by some source.
 | 
						|
    To listen for events in this stream, ***subscribe*** to the `Observable`.
 | 
						|
    These subscriptions specify the actions to take when the web request
 | 
						|
    produces a success event (with the hero data in the event payload) or a fail event (with the error in the payload).
 | 
						|
 | 
						|
:marked
 | 
						|
  With a basic understanding of the component, you're ready to look inside the `HeroService`.
 | 
						|
 | 
						|
a#HeroService
 | 
						|
.l-main-section#fetch-data
 | 
						|
:marked
 | 
						|
  ## Fetch data with http.get
 | 
						|
 | 
						|
  In many of the previous samples the app faked the interaction with the server by
 | 
						|
  returning mock heroes in a service like this one:
 | 
						|
+makeExample('toh-4/ts/app/hero.service.ts', 'just-get-heroes')(format=".")
 | 
						|
:marked
 | 
						|
  You can revise that `HeroService` to get the heroes from the server using the !{_Angular_Http} client service:
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'v1', 'app/toh/hero.service.ts (revised)')
 | 
						|
 | 
						|
:marked
 | 
						|
  Notice that the !{_Angular_Http} client service is
 | 
						|
  [injected](dependency-injection.html) into the `HeroService` constructor.
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'ctor')
 | 
						|
:marked
 | 
						|
  Look closely at how to call `!{_priv}http.get`:
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'http-get', 'app/toh/hero.service.ts (getHeroes)')(format=".")
 | 
						|
:marked
 | 
						|
  You pass the resource URL to `get` and it calls the server which returns heroes.
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    The server returns heroes once you've set up the [in-memory web api](#in-mem-web-api)
 | 
						|
    described in the appendix below.
 | 
						|
    Alternatively, you can temporarily target a JSON file by changing the endpoint URL:
 | 
						|
  +makeExample('server-communication/ts/app/toh/hero.service.ts', 'endpoint-json')(format=".")
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  :marked
 | 
						|
    <a id="rxjs"></a>
 | 
						|
    If you are familiar with asynchronous methods in modern JavaScript, you might expect the `get` method to return a
 | 
						|
    [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
 | 
						|
    You'd expect to chain a call to `then()` and extract the heroes.
 | 
						|
    Instead you're calling a `map()` method.
 | 
						|
    Clearly this is not a promise.
 | 
						|
 | 
						|
    In fact, the `http.get` method returns an **Observable** of HTTP Responses (`Observable<Response>`) from the RxJS library
 | 
						|
    and `map` is one of the RxJS *operators*.
 | 
						|
 | 
						|
  .l-main-section
 | 
						|
  :marked
 | 
						|
    # RxJS library
 | 
						|
    [RxJS](https://github.com/ReactiveX/RxJS) ("Reactive Extensions") is a 3rd party library, endorsed by Angular,
 | 
						|
    that implements the [*asynchronous observable*](https://www.youtube.com/watch?v=UHI0AzD_WfY "Rob Wormald on observables") pattern.
 | 
						|
 | 
						|
    All of the Developer Guide samples have installed the RxJS npm package and loaded via `system.js`
 | 
						|
    because observables are used widely in Angular applications.
 | 
						|
 | 
						|
    The app needs it when working with the HTTP client.
 | 
						|
    Additionally, you must take a critical extra step to make RxJS observables usable.
 | 
						|
 | 
						|
    ### Enable RxJS operators
 | 
						|
    The RxJS library is large.
 | 
						|
    Size matters when building a production application and deploying it to mobile devices.
 | 
						|
    You should include only necessary features.
 | 
						|
 | 
						|
    Accordingly, Angular exposes a stripped down version of `Observable` in the `rxjs/Observable`
 | 
						|
    module that lacks most of the operators such as the `map` method you
 | 
						|
    called above in `getHeroes`.
 | 
						|
 | 
						|
    It's up to you to add the operators you need.
 | 
						|
 | 
						|
    You could add _every_ RxJS operator with a single import statement.
 | 
						|
    While that is the easiest thing to do, you'd pay a penalty in extended launch time
 | 
						|
    and application size because the full library is so big.
 | 
						|
 | 
						|
    Since this app only uses a few operators, it's better to import each `Observable`
 | 
						|
    operator and static class method, one-by-one, for a custom *Observable*
 | 
						|
    implementation tuned
 | 
						|
    precisely to the app's requirements. Put the `import` statements in one `app/rxjs-operators.ts` file.
 | 
						|
  +makeExample('server-communication/ts/app/rxjs-operators.ts', null, 'app/rxjs-operators.ts')(format=".")
 | 
						|
  :marked
 | 
						|
    If you forget an operator, the TypeScript compiler warns that it's missing and you'll update this file.
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      The app doesn't need _all_ of these particular operators in the `HeroService` — just `map`, `catch` and `throw`.
 | 
						|
      The other operators are for later, in the *Wiki* example [below](#more-observables).
 | 
						|
  :marked
 | 
						|
    Finally, import `rxjs-operator` into `app.component.ts`:
 | 
						|
  +makeExample('server-communication/ts/app/app.component.ts', 'import-rxjs', 'app/app.component.ts (import rxjs)')(format=".")
 | 
						|
 | 
						|
  :marked
 | 
						|
    Now continue to the next section to return to the `HeroService`.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
a#extract-data
 | 
						|
:marked
 | 
						|
  ## Process the response object
 | 
						|
  Remember that the `getHeroes()` method used an `!{_priv}extractData` helper method to map the `!{_priv}http.get` response object to heroes:
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'extract-data', 'app/toh/hero.service.ts (excerpt)')(format=".")
 | 
						|
:marked
 | 
						|
  The `response` object doesn't hold the data in a form the app can use directly.
 | 
						|
  You must parse the response data into a JSON object.
 | 
						|
 | 
						|
  ### Parse to JSON
 | 
						|
block parse-json
 | 
						|
  :marked
 | 
						|
    The response data are in JSON string form.
 | 
						|
    The app must parse that string into JavaScript objects by calling `response.json()`.
 | 
						|
 | 
						|
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      This is not Angular's own design.
 | 
						|
      The Angular HTTP client follows the Fetch specification for the
 | 
						|
      [response object](https://fetch.spec.whatwg.org/#response-class) returned by the `Fetch` function.
 | 
						|
      That spec defines a `json()` method that parses the response body into a JavaScript object.
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Don't expect the decoded JSON to be the heroes !{_array} directly.
 | 
						|
    This server always wraps JSON results in an object with a `data`
 | 
						|
    property. You have to unwrap it to get the heroes.
 | 
						|
    This is conventional web API behavior, driven by
 | 
						|
    [security concerns](https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside).
 | 
						|
 | 
						|
.alert.is-important
 | 
						|
  :marked
 | 
						|
     Make no assumptions about the server API.
 | 
						|
     Not all servers return an object with a `data` property.
 | 
						|
:marked
 | 
						|
  ### Do not return the response object
 | 
						|
  The `getHeroes()` method _could_ have returned the HTTP response but this wouldn't
 | 
						|
  be a best practice.
 | 
						|
  The point of a data service is to hide the server interaction details from consumers.
 | 
						|
  The component that calls the `HeroService` only wants heroes and is kept separate
 | 
						|
  from getting them, the code dealing with where they come from, and the response object.
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  .callout.is-important
 | 
						|
    header HTTP GET is delayed
 | 
						|
    :marked
 | 
						|
      The `!{_priv}http.get` does **not send the request just yet.** This observable is
 | 
						|
      [*cold*](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md#cold-vs-hot-observables),
 | 
						|
      which means that the request won't go out until something *subscribes* to the observable.
 | 
						|
      That *something* is the [HeroListComponent](#subscribe).
 | 
						|
 | 
						|
a#error-handling
 | 
						|
:marked
 | 
						|
  ### Always handle errors
 | 
						|
 | 
						|
  An important part of dealing with I/O is anticipating errors by preparing to catch them
 | 
						|
  and do something with them. One way to handle errors is to pass an error message
 | 
						|
  back to the component for presentation to the user,
 | 
						|
  but only if it says something that the user can understand and act upon.
 | 
						|
  
 | 
						|
  This simple app conveys that idea, albeit imperfectly, in the way it handles a `getHeroes` error.
 | 
						|
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'error-handling', 'app/toh/hero.service.ts (excerpt)')(format=".")
 | 
						|
 | 
						|
block error-handling
 | 
						|
  :marked
 | 
						|
    The `catch` operator passes the error object from `http` to the `handleError` method.
 | 
						|
    The `handleError` method transforms the error into a developer-friendly message, 
 | 
						|
    logs it to the console, and returns the message in a new, failed observable via `Observable.throw`.
 | 
						|
 | 
						|
a#subscribe
 | 
						|
a#hero-list-component
 | 
						|
h3 #[b HeroListComponent] error handling
 | 
						|
block hlc-error-handling
 | 
						|
  :marked
 | 
						|
    Back in the `HeroListComponent`, in `!{_priv}heroService.getHeroes()`,
 | 
						|
    the `subscribe` function has a second function parameter to handle the error message.
 | 
						|
    It sets an `errorMessage` variable that's bound conditionally in the `HeroListComponent` template.
 | 
						|
 | 
						|
+makeExample('server-communication/ts/app/toh/hero-list.component.ts', 'getHeroes', 'app/toh/hero-list.component.ts (getHeroes)')(format=".")
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Want to see it fail? In the `HeroService`, reset the api endpoint to a bad value. Afterward, remember to restore it.
 | 
						|
 | 
						|
 | 
						|
<a id="update"></a>
 | 
						|
<a id="post"></a>
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Send data to the server
 | 
						|
 | 
						|
  So far you've seen how to retrieve data from a remote location using an HTTP service.
 | 
						|
  Now you'll add the ability to create new heroes and save them in the backend.
 | 
						|
 | 
						|
  You'll write a method for the `HeroListComponent` to call, an `addHero()` method, that takes
 | 
						|
  just the name of a new hero and returns an `Observable` of `Hero`. It begins like this:
 | 
						|
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'addhero-sig')(format=".")
 | 
						|
 | 
						|
:marked
 | 
						|
  To implement it, you must know the server's API for creating heroes.
 | 
						|
 | 
						|
  [This sample's data server](#server) follows typical REST guidelines.
 | 
						|
  It expects a [`POST`](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) request
 | 
						|
  at the same endpoint as `GET` heroes.
 | 
						|
  It expects the new hero data to arrive in the body of the request,
 | 
						|
  structured like a `Hero` entity but without the `id` property.
 | 
						|
  The body of the request should look like this:
 | 
						|
 | 
						|
code-example(format="." language="javascript").
 | 
						|
  { "name": "Windstorm" }
 | 
						|
:marked
 | 
						|
  The server generates the `id` and returns the entire `JSON` representation
 | 
						|
  of the new hero including its generated id. The hero arrives tucked inside a response object
 | 
						|
  with its own `data` property.
 | 
						|
 | 
						|
  Now that you know how the API works, implement `addHero()`as follows:
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  +makeExample('server-communication/ts/app/toh/hero.service.ts', 'import-request-options', 'app/toh/hero.service.ts (additional imports)')(format=".")
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'addhero', 'app/toh/hero.service.ts (addHero)')(format=".")
 | 
						|
 | 
						|
:marked
 | 
						|
  ### Headers
 | 
						|
 | 
						|
  In the `headers` object, the `Content-Type` specifies that the body represents JSON.
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  :marked
 | 
						|
    Next, the `headers` object is used to configure the `options` object. The `options`
 | 
						|
    object is a new instance of `RequestOptions`, a class that allows you to specify
 | 
						|
    certain settings when instantiating a request. In this way, [headers](../api/http/index/Headers-class.html) is one of the [RequestOptions](../api/http/index/RequestOptions-class.html).
 | 
						|
 | 
						|
    In the `return` statement, `options` is the *third* argument of the `post` method, as shown above.
 | 
						|
 | 
						|
:marked
 | 
						|
  ### JSON results
 | 
						|
 | 
						|
  As with `getHeroes()`, use the `!{_priv}extractData()` helper to [extract the data](#extract-data)
 | 
						|
  from the response.
 | 
						|
 | 
						|
block hero-list-comp-add-hero
 | 
						|
  :marked
 | 
						|
    Back in the `HeroListComponent`, *its* `addHero()` method subscribes to the observable returned by the *service's* `addHero()` method.
 | 
						|
    When the data arrive it pushes the new hero object into its `heroes` array for presentation to the user.
 | 
						|
+makeExample('server-communication/ts/app/toh/hero-list.component.ts', 'addHero', 'app/toh/hero-list.component.ts (addHero)')(format=".")
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  h2#promises Fall back to promises
 | 
						|
  :marked
 | 
						|
    Although the Angular `http` client API returns an `Observable<Response>` you can turn it into a
 | 
						|
    [`Promise<Response>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
 | 
						|
    It's easy to do, and in simple cases, a promise-based version looks much
 | 
						|
    like the observable-based version.
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      While promises may be more familiar, observables have many advantages.
 | 
						|
 | 
						|
  :marked
 | 
						|
    Here is a comparison of the `HeroService` using promises versus observables,
 | 
						|
    highlighting just the parts that are different.
 | 
						|
  +makeTabs(
 | 
						|
    'server-communication/ts/app/toh/hero.service.promise.ts,server-communication/ts/app/toh/hero.service.ts',
 | 
						|
    'methods, methods',
 | 
						|
    'app/toh/hero.service.promise.ts (promise-based), app/toh/hero.service.ts (observable-based)')
 | 
						|
  :marked
 | 
						|
    You can follow the promise `then(this.extractData).catch(this.handleError)` pattern as in
 | 
						|
    this example.
 | 
						|
 | 
						|
    Alternatively, you can call `toPromise(success, fail)`. The observable's `map` callback moves to the first *success* parameter and its `catch` callback to the second *fail* parameter in this pattern: `.toPromise(this.extractData, this.handleError)`.
 | 
						|
 | 
						|
    The `errorHandler` forwards an error message as a failed promise instead of a failed `observable`.
 | 
						|
 | 
						|
    The diagnostic *log to console* is just one more `then` in the promise chain.
 | 
						|
 | 
						|
    You have to adjust the calling component to expect a `Promise` instead of an `observable`:
 | 
						|
 | 
						|
  +makeTabs(
 | 
						|
    'server-communication/ts/app/toh/hero-list.component.promise.ts, server-communication/ts/app/toh/hero-list.component.ts',
 | 
						|
    'methods, methods',
 | 
						|
    'app/toh/hero-list.component.promise.ts (promise-based), app/toh/hero-list.component.ts (observable-based)')
 | 
						|
  :marked
 | 
						|
    The only obvious difference is that you call `then` on the returned promise instead of `subscribe`.
 | 
						|
    Both methods take the same functional arguments.
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      The less obvious but critical difference is that these two methods return very different results.
 | 
						|
 | 
						|
      The promise-based `then` returns another promise. You can keep chaining more `then` and `catch` calls, getting a new promise each time.
 | 
						|
 | 
						|
      The `subscribe` method returns a `Subscription`. A `Subscription` is not another `Observable`.
 | 
						|
      It's the end of the line for observables. You can't call `map` on it or call `subscribe` again.
 | 
						|
      The `Subscription` object has a different purpose, signified by its primary method, `unsubscribe`.
 | 
						|
 | 
						|
      To understand the implications and consequences of subscriptions, watch [Ben Lesh's talk on observables](https://www.youtube.com/watch?v=3LKMwkuK0ZE) or his video course on [egghead.io](https://egghead.io/lessons/rxjs-rxjs-observables-vs-promises).
 | 
						|
 | 
						|
h2#cors Cross-Origin Requests: Wikipedia example
 | 
						|
:marked
 | 
						|
  You just learned how to make `XMLHttpRequests` using the !{_Angular_Http} service.
 | 
						|
  This is the most common approach for server communication, but it doesn't work in all scenarios.
 | 
						|
 | 
						|
  For security reasons, web browsers block `XHR` calls to a remote server whose origin is different from the origin of the web page.
 | 
						|
  The *origin* is the combination of URI scheme, hostname, and port number.
 | 
						|
  This is called the [same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy).
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Modern browsers do allow `XHR` requests to servers from a different origin if the server supports the
 | 
						|
    [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) protocol.
 | 
						|
    If the server requires user credentials, you'll enable them in the [request headers](#headers).
 | 
						|
 | 
						|
:marked
 | 
						|
  Some servers do not support CORS but do support an older, read-only alternative called [JSONP](https://en.wikipedia.org/wiki/JSONP).
 | 
						|
  Wikipedia is one such server.
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    This [Stack Overflow answer](http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about/2067584#2067584) covers many details of JSONP.
 | 
						|
:marked
 | 
						|
  ### Search wikipedia
 | 
						|
 | 
						|
  Here is a simple search that shows suggestions from Wikipedia as the user
 | 
						|
  types in a text box:
 | 
						|
 | 
						|
figure.image-display
 | 
						|
  img(src='/resources/images/devguide/server-communication/wiki-1.gif' alt="Wikipedia search app (v.1)" width="250")
 | 
						|
 | 
						|
block wikipedia-jsonp+
 | 
						|
  :marked
 | 
						|
    Wikipedia offers a modern `CORS` API and a legacy `JSONP` search API. This example uses the latter.
 | 
						|
    The Angular `Jsonp` service both extends the `!{_Http}` service for JSONP and restricts you to `GET` requests.
 | 
						|
    All other HTTP methods throw an error because JSONP is a read-only facility.
 | 
						|
 | 
						|
    As always, wrap the interaction with an Angular data access client service inside a dedicated service, here called `WikipediaService`.
 | 
						|
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wikipedia.service.ts',null,'app/wiki/wikipedia.service.ts')
 | 
						|
  :marked
 | 
						|
    The constructor expects Angular to inject its `jsonp` service, which 
 | 
						|
    is available because `JsonpModule` is in the root `@NgModule` `imports` array
 | 
						|
    in `app.module.ts`.
 | 
						|
 | 
						|
  <a id="query-parameters"></a>
 | 
						|
  :marked
 | 
						|
    ### Search parameters
 | 
						|
    The [Wikipedia "opensearch" API](https://www.mediawiki.org/wiki/API:Opensearch)
 | 
						|
    expects four parameters (key/value pairs) to arrive in the request URL's query string.
 | 
						|
    The keys are `search`, `action`, `format`, and `callback`.
 | 
						|
    The value of the `search` key is the user-supplied search term to find in Wikipedia.
 | 
						|
    The other three are the fixed values "opensearch", "json", and "JSONP_CALLBACK" respectively.
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      The `JSONP` technique requires that you pass a callback function name to the server in the query string: `callback=JSONP_CALLBACK`.
 | 
						|
      The server uses that name to build a JavaScript wrapper function in its response, which Angular ultimately calls to extract the data.
 | 
						|
      All of this happens under the hood.
 | 
						|
  :marked
 | 
						|
    If you're looking for articles with the word "Angular", you could construct the query string by hand and call `jsonp` like this:
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wikipedia.service.1.ts','query-string')(format='.')
 | 
						|
  :marked
 | 
						|
    In more parameterized examples you could build the query string with the Angular `URLSearchParams` helper:
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wikipedia.service.ts','search-parameters','app/wiki/wikipedia.service.ts (search parameters)')(format=".")
 | 
						|
  :marked
 | 
						|
    This time you call `jsonp` with *two* arguments: the `wikiUrl` and an options object whose `search` property is the `params` object.
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wikipedia.service.ts','call-jsonp','app/wiki/wikipedia.service.ts (call jsonp)')(format=".")
 | 
						|
  :marked
 | 
						|
    `Jsonp` flattens the `params` object into the same query string you saw earlier, putting the request on the wire.
 | 
						|
 | 
						|
  <a id="wikicomponent"></a>
 | 
						|
  :marked
 | 
						|
    ### The WikiComponent
 | 
						|
 | 
						|
    Now that you have a service that can query the Wikipedia API
 | 
						|
    turn to the component (template and class) that takes user input and displays search results.
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki.component.html', null, 'app/wiki/wiki.component.html')
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki.component.ts', null, 'app/wiki/wiki.component.ts')
 | 
						|
  :marked
 | 
						|
    The template presents an `<input>` element *search box* to gather search terms from the user,
 | 
						|
    and calls a `search(term)` method after each `keyup` event.
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki.component.html', 'keyup', 'wiki/wiki.component.html')(format='.')
 | 
						|
  :marked
 | 
						|
    The component's `search(term)` method delegates to the `WikipediaService`, which returns an 
 | 
						|
    observable array of string results (`Observable<string[]>`).
 | 
						|
    Instead of subscribing to the observable inside the component, as in the `HeroListComponent`,
 | 
						|
    the app forwards the observable result to the template (via `items`) where the `async` pipe 
 | 
						|
    in the `ngFor` handles the subscription. Read more about [async pipes](pipes.html#async-pipe)
 | 
						|
    in the [Pipes](pipes.html) page.
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      The [async pipe](pipes.html#async-pipe) is a good choice in read-only components where the component has no need to interact with the data.
 | 
						|
 | 
						|
      `HeroListComponent` can't use the pipe because `addHero()` pushes newly created heroes into the list.
 | 
						|
 | 
						|
  :marked
 | 
						|
    ## A wasteful app
 | 
						|
 | 
						|
    The wikipedia search makes too many calls to the server.
 | 
						|
    It is inefficient, and potentially expensive on mobile devices with limited data plans.
 | 
						|
 | 
						|
    ### 1. Wait for the user to stop typing
 | 
						|
    Presently, the code calls the server after every key stroke.
 | 
						|
    It should only make requests when the user *stops typing* .
 | 
						|
    Here's how it will work after refactoring:
 | 
						|
  figure.image-display
 | 
						|
    img(src='/resources/images/devguide/server-communication/wiki-2.gif' alt="Wikipedia search app (v.2)" width="250")
 | 
						|
  :marked
 | 
						|
    ### 2. Search when the search term changes
 | 
						|
 | 
						|
    Suppose a user enters the word *angular* in the search box and pauses for a while.
 | 
						|
    The application issues a search request for *angular*.
 | 
						|
 | 
						|
    Then the user backspaces over the last three letters, *lar*, and immediately re-types *lar* before pausing once more.
 | 
						|
    The search term is still _angular_. The app shouldn't make another request.
 | 
						|
 | 
						|
    ### 3. Cope with out-of-order responses
 | 
						|
 | 
						|
    The user enters *angular*, pauses, clears the search box, and enters *http*.
 | 
						|
    The application issues two search requests, one for *angular* and one for *http*.
 | 
						|
 | 
						|
    Which response arrives first? It's unpredictable.
 | 
						|
    A load balancer could dispatch the requests to two different servers with different response times.
 | 
						|
    The results from the first *angular* request might arrive after the later *http* results.
 | 
						|
    The user will be confused if the *angular* results display to the *http* query.
 | 
						|
 | 
						|
    When there are multiple requests in-flight, the app should present the responses
 | 
						|
    in the original request order. That won't happen if *angular* results arrive last.
 | 
						|
 | 
						|
    <a id="more-observables"></a>
 | 
						|
    ## More fun with observables
 | 
						|
    You can address these problems and improve the app with the help of some nifty observable operators.
 | 
						|
 | 
						|
    You could make changes to the `WikipediaService`, but for a better
 | 
						|
    user experience, create a copy of the `WikiComponent` instead and make it smarter.
 | 
						|
    Here's the `WikiSmartComponent` which uses the same template.
 | 
						|
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', null, 'app/wiki/wiki-smart.component.ts')
 | 
						|
  :marked
 | 
						|
    ### Create a stream of search terms
 | 
						|
 | 
						|
    The template still binds to the search box `keyup` event and passes the complete search box value
 | 
						|
    into the component's `search` method after every user keystroke.
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki.component.html', 'keyup', 'app/wiki/wiki.component.html (input)')(format='.')
 | 
						|
  :marked
 | 
						|
    The `WikiSmartComponent` turns the search box values into an observable _stream of search terms_
 | 
						|
    with the help of a `Subject` which you import from the RxJS observable library:
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'import-subject', 'app/wiki/wiki-smart.component.ts')
 | 
						|
  :marked
 | 
						|
    The component creates a `searchTermStream` as a `Subject` of type `string`.
 | 
						|
    The `search` method adds each new search box value to that stream via the subject's `next` method.
 | 
						|
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'subject', 'app/wiki/wiki-smart.component.ts')(format='.')
 | 
						|
 | 
						|
  :marked
 | 
						|
    ### Listen for search terms
 | 
						|
 | 
						|
    Earlier, you passed each search term directly to the service and bound the template to the service results.
 | 
						|
 | 
						|
    Now you listen to the *stream of search terms*, manipulating the stream before it reaches the `WikipediaService`.
 | 
						|
  +makeExample('server-communication/ts/app/wiki/wiki-smart.component.ts', 'observable-operators', 
 | 
						|
  'app/wiki/wiki-smart.component.ts')(format='.')
 | 
						|
  :marked
 | 
						|
    Wait for the user to stop typing for at least 300 milliseconds
 | 
						|
    ([_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)).
 | 
						|
 | 
						|
    The `WikipediaService` returns a separate observable of string arrays (`Observable<string[]>`) for each request.
 | 
						|
    There could be multiple requests *in-flight*, all awaiting the server's reply,
 | 
						|
    which means multiple *observables-of-strings* could arrive at any moment in any order.
 | 
						|
 | 
						|
    The [_switchMap_](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/flatmaplatest.md)
 | 
						|
    (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 displayed list of search results stays in sync with the user's sequence of search terms.
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      You added the `debounceTime`, `distinctUntilChanged`, and `switchMap` operators to the RxJS `Observable` class
 | 
						|
      in `rxjs-operators` as [described above](#rxjs).
 | 
						|
 | 
						|
a#xsrf
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Guarding against Cross-Site Request Forgery
 | 
						|
 | 
						|
  In a cross-site request forgery (CSRF or XSRF), an attacker tricks the user into visiting
 | 
						|
  a different web page with malignant code that secretly sends a malicious request to your application's web server,
 | 
						|
  
 | 
						|
  The server and client application must work together to thwart this attack.
 | 
						|
  Angular's `Http` client does its part by applying a default `CookieXSRFStrategy` automatically to all requests.
 | 
						|
 | 
						|
  The `CookieXSRFStrategy` supports a common anti-XSRF technique in which the server sends a randomly
 | 
						|
  generated authentication token in a cookie named `XSRF-TOKEN`. 
 | 
						|
  The HTTP client adds an `X-XSRF-TOKEN` header with that token value to subsequent requests. 
 | 
						|
  The server receives both the cookie and the header, compares them, and processes the request only if the cookie and header match.
 | 
						|
  
 | 
						|
  See the [XSRF topic on the Security page](security.html#xsrf) for more information about XSRF and Angular's `XSRFStrategy` counter measures.
 | 
						|
 | 
						|
a#in-mem-web-api
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Appendix: Tour of Heroes in-memory server
 | 
						|
 | 
						|
  If the app only needed to retrieve data, you could get the heroes from a `heroes.json` file:
 | 
						|
+makeJson('server-communication/ts/app/heroes.json', null, 'app/heroes.json')(format=".")
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    You wrap the heroes array in an object with a `data` property for the same reason that a data server does:
 | 
						|
    to mitigate the [security risk](http://stackoverflow.com/questions/3503102/what-are-top-level-json-arrays-and-why-are-they-a-security-risk)
 | 
						|
    posed by top-level JSON arrays.
 | 
						|
:marked
 | 
						|
  You'd set the endpoint to the JSON file like this:
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'endpoint-json', 'app/toh/hero.service.ts')(format=".")
 | 
						|
 | 
						|
- var _a_ca_class_with = _docsFor === 'ts' ? 'a custom application class with' : ''
 | 
						|
:marked
 | 
						|
  The *get heroes* scenario would work,
 | 
						|
  but since the app can't save changes to a JSON file, it needs a web API server.
 | 
						|
  Because there isn't a real server for this demo, 
 | 
						|
  it uses an *in-memory web API simulator* instead.
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    The in-memory web api is not part of the Angular core.
 | 
						|
    It's an optional service in its own `angular-in-memory-web-api` library
 | 
						|
    installed with npm (see `package.json`) and
 | 
						|
    registered for module loading by SystemJS (see `systemjs.config.js`).
 | 
						|
 | 
						|
:marked
 | 
						|
  The in-memory web API gets its data from !{_a_ca_class_with} a `createDb()`
 | 
						|
  method that returns a map whose keys are collection names and whose values
 | 
						|
  are !{_array}s of objects in those collections.
 | 
						|
 | 
						|
  Here's the class for this sample, based on the JSON data:
 | 
						|
+makeExample('server-communication/ts/app/hero-data.ts', null, 'app/hero-data.ts')(format=".")
 | 
						|
:marked
 | 
						|
  Ensure that the `HeroService` endpoint refers to the web API:
 | 
						|
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'endpoint', 'app/toh/hero.service.ts')(format=".")
 | 
						|
 | 
						|
block redirect-to-web-api
 | 
						|
  :marked
 | 
						|
    Finally, redirect client HTTP requests to the in-memory web API by
 | 
						|
    adding the `InMemoryWebApiModule` to the `AppModule.imports` list.
 | 
						|
    At the same time, call its `forRoot` configuration method with the `HeroData` class.
 | 
						|
  +makeExample('server-communication/ts/app/app.module.ts', 'in-mem-web-api', 'app/app.module.ts')(format=".")
 | 
						|
  :marked
 | 
						|
    ### How it works
 | 
						|
 | 
						|
    Angular's `http` service delegates the client/server communication tasks
 | 
						|
    to a helper service called the `XHRBackend`.
 | 
						|
 | 
						|
    Using standard Angular provider registration techniques, the `InMemoryWebApiModule`
 | 
						|
    replaces the default `XHRBackend` service with its own in-memory alternative.
 | 
						|
    At the same time, the `forRoot` method initializes the in-memory web API with the *seed data* from the mock hero dataset.
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      The `forRoot` method name is a strong reminder that you should only call the `InMemoryWebApiModule` _once_,
 | 
						|
      while setting the metadata for the root `AppModule`. Don't call it again.
 | 
						|
:marked
 | 
						|
  Here is the final, revised version of <span ngio-ex>app/app.module.ts</span>, demonstrating these steps.
 | 
						|
 | 
						|
+makeExcerpt('app/app.module.ts')
 | 
						|
.alert.is-important
 | 
						|
  :marked
 | 
						|
    Import the `InMemoryWebApiModule` _after_ the `HttpModule` to ensure that 
 | 
						|
    the `XHRBackend` provider of the `InMemoryWebApiModule` supersedes all others.
 | 
						|
:marked
 | 
						|
  See the full source code in the <live-example></live-example>.
 |