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

前言:html

在這裏,我描述三個場景,即系統的註冊與登陸,及登陸後的操做:前端

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

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

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

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

 

前期準備:json

在繼續以前,咱們須要一些準備工做,即建立一個後臺服務,包括註冊、登陸及查詢這三個接口,這裏包括有三個接口分別以下:api

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

下載及方法:session

git clone https://github.com/auth0/nodejs-jwt-authentication-sample.git

npm install

node server.js

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

接下來,建立界面元素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組件:

 

@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')
);
}

查詢

 

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');

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

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

相關文章
相關標籤/搜索