Angular2學習筆記四(之Http通訊)

前言

接上篇,雖然一會兒從建立項目就到了http通訊,看上去是有點猴急,但沒辦法,走到哪裏就算哪裏吧。在這裏,我描述三個場景,即系統的註冊與登陸,及登陸後的操做。html

一、註冊場景,前端頁面傳入用戶名密碼,經過一個api接口傳到後臺,在後臺對這用戶及密碼進行保存;前端

二、登陸場景,前端用戶傳入用戶名及密碼,經過api接口傳到後臺,在後臺進行配對,若是配對成功,則在後臺派發(返回)一個令牌(id_token,下同),經過這個令牌做爲用戶已經登陸的惟一憑證,須要保存到用戶本地存儲(localStorage),之後做後續操做;node

三、登陸後操做,當用戶須要受權操做時,那麼首先得獲取本地存儲(localStorage)中的令牌,將令牌傳到後臺,若是匹配成功,則容許操做,不然不容許操做。git

之後三個場景大致描述了一個系統註冊登陸的思路。下面,我將從這三個思路出發,講述Angular2中http與後臺通訊的過程。github

前期準備

在繼續以前,咱們須要一些準備工做,即建立一個後臺服務,包括註冊、登陸及查詢這三個接口。由於這裏不關注後臺怎麼建立,因此我也從網上一位小哥這裏找到現成的後臺服務,這裏包括有三個接口分別以下:npm

http://localhost:3001/users
http://localhost:3001/sessions/create
http://localhost:3001/api/protected/random-quote

下載及方法:json

git clone https://github.com/auth0/nodejs-jwt-authentication-sample.git
npm install
node server.js

按照上面的步驟,後臺服務就算準備完成,能夠繼續往下看了。api

接下來,建立界面元素post-component.html服務器

<form (ngSubmit)="register(registerForm.value)" #registerForm="ngForm">
  <div class="text-center">
    <h2>註冊</h2>
  </div>
  <div class="form-group">
    <label for="username">Name</label>
    <input type="text" class="form-control" id="username" required [(ngModel)]="model.username" name="username">
  </div>
  <div class="form-group">
    <label for="password">Alter Ego</label>
    <input type="text" class="form-control" id="password" required [(ngModel)]="model.password" name="password">
  </div>
  <button type="submit" class="btn btn-success">Submit</button>
</form>

<form (ngSubmit)="onLogin(loginForm.value)" #loginForm="ngForm">
  <div class="text-center">
    <h2>登陸</h2>
  </div>
  <div class="form-group">
    <label for="username2">Name</label>
    <input type="text" class="form-control" id="username2" required [(ngModel)]="model.username2" name="username2">
  </div>
  <div class="form-group">
    <label for="password2">Alter Ego</label>
    <input type="text" class="form-control" id="password2" required [(ngModel)]="model.password2" name="password2">
  </div>
  <button type="submit" class="btn btn-success">Submit</button>
</form>

<button id="input" (click)="getSecretQuote()">登陸以後才能獲取數據</button>

接下來建立PostComponent.ts組件session

@Component({
      selector: 'post-client',
      templateUrl: './post-component.html',
    })
    
    export class PostComponent {
      model: any;

      constructor(private http: Http) {
        this.model = {};
      }
      //把代碼寫這裏啦
    }

這樣,咱們就已經建立好工做區模板,能夠盡情在哪裏寫東西了。

再準備準備

在進行以前,咱們看下angular2中,http api方法的傳參數形式

http.get(url: string, options?: RequestOptionsArgs) : Observable<Response>
http.post(url: string, body: any, options?: RequestOptionsArgs) : Observable<Response>

能夠看到,根據其參數url地址, body:any及options?: RequestOptionsArgs參數來提交對應的數據信息,其中body表示傳遞到服務器端的數據信息,options表示頭部驗證信息。兩個方法都返回一個可觀察對象Observable,咱們能夠經過subscribe方法獲得裏面的值並做後繼處理。這樣,咱們能夠獲得如下代碼處理方法

this.http.post(url: string, body: any, options?: RequestOptionsArgs).subscribe(function (data) {
   console.log(data)
})

以上的處理方式並無什麼太大的問題,但總感受仍是有點小小的欠缺。

結果處理之可觀察對象Observable

咱們經過Http以及Jsonp的api接口能夠知道,默認返回值都是可觀察對象 Observable< Response >。能夠把可觀察對象 Observable 看作一個由某些「源」發佈的事件流。 經過 訂閱 到可觀察對象 Observable ,咱們監聽(subscribe)這個流中的事件。 在這些訂閱中,咱們指定了當 Web 請求生成了一個成功事件 ( 有效載荷是英雄數據 ) 或失敗事件 ( 有效載荷是錯誤對象 ) 時該如何採起行動,如示例中所示。

咱們的服務能夠返回 HTTP 響應對象Response。但這可不是一個好主意! 數據服務的重點在於,對消費者隱藏與服務器交互的細節。其實上,咱們最關心的仍是獲取到的返回數據信息,這時候咱們就能夠利用RxJS庫來對事件流進行一些額外的處理。

RxJS("Reactive Extensions" 的縮寫)是一個被 Angular 承認的第三方庫,它實現了異步可觀察對象 (asynchronous observable) 模式。Rxjs庫中包含不少對事件流進行處理的方法,例如map,distinctUntilChanged等操做符。

針對返回數據是json格式的響應對象,能夠把Response解析成 JavaScript 對象——只要調一下 response.json() 就能夠了,這時候咱們就能夠利用map操做符來進行處理,例如,咱們將上面的方法升級下

this.http.post(url: string, body: any, options?: RequestOptionsArgs).map((rsp:Response)=>{
return rsp.json()
})
.subscribe((data) => {
console.log(data);
});

注意,這裏.map用到了rxjs庫,須要導入這個庫。

結果處理之Promise

雖然 Angular 的 http 客戶端 API 返回的是 Observable<Response> 類型的對象,但咱們也能夠把它轉成 Promise<Response>。這很容易,只須要調用可觀察對象 Observable< Response >的方法toPromise()就可以進行轉化。

this.http.post(url: string, body: any, options?: RequestOptionsArgs).toPromise()
.then((rsp: Response) => {
console.log(rsp)
});

註冊

經過上面的講述,如今執行http通訊也變得簡單多了。上代碼

register(data) {
    var username = data.username;
    var password = data.password;
    var body = "username=" + username + "&password=" + password + "&extra=color";
    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    this.http.post('http://localhost:3001/users', body, {
      headers: headers
    })
      .map(res => res.json())
      .subscribe(
        data => console.log(data),
        err => console.log(err),
        () => console.log('Register Complete')
      );
  }

登陸

onLogin(data) {
    var username = data.username2;
    var password = data.password2;
    var body = "username=" + username + "&password=" + password + "&extra=color";
    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    this.http.post('http://localhost:3001/sessions/create', body, {
      headers: headers
    })
      .map(res => res.json())
      .subscribe(
        data => {
          localStorage.setItem('id_token', data.id_token), console.log(data)
        },
        err => console.log(err),
        () => console.log('Register Complete')
      );
  }

這裏須要注意,localStorage.setItem('id_token', data.id_token)這句代碼,表明將獲取的令牌保存到本地存儲,這是表明本用戶已經登陸的惟一憑證。

查詢

getSecretQuote() {

    var jwt = localStorage.getItem('id_token');
    var authHeader = new Headers();
    if (jwt) {
      authHeader.append('Authorization', 'Bearer ' + jwt);
    }

    this.http.get('http://localhost:3001/api/protected/random-quote', {
      headers: authHeader
    })
      .map(res => res.text())
      .subscribe(
        data => console.log(data),
        err => console.log(err),
        () => console.log('Secret Quote Complete')
      );

  }

在這裏,執行查詢前須要把本地存儲中的令牌帶到頭部,

var jwt = localStorage.getItem('id_token');

這樣後臺就能夠在查詢前對令牌進行比對,若是比對成功,則返回結果。

這樣,一個簡單的註冊--登陸--查詢思路便講解完成了

Angular2 Http註冊登陸驗證

Angular2 Http

相關文章
相關標籤/搜索