網站有了一堆的元素、動畫、圖片、文字,可能看起來很炫很厲害,但是這樣就只能是靜態的網站,想要實現購物車、會員機制、留言板、討論區、投票區、訊息發佈、商品發佈等等功能,進而設計出可與網友進行互動的功能。而要實現這些功能,不外乎就是一直呼叫 API,然後透過後端和資料庫的處理,再將資料傳回給網站。
前端和後端的連結,就是透過 Http 方法,包含 get、post、head、put、patch 和 delete。接下來就來說明如何在 Angular 2 中實現 HTTP 方法。
RxJS是一個第三方函式庫,由 Angular 贊助,實現異步觀察模式。Angular 默認就有安裝 RxJS,因為 Observable 模式被廣泛在應用在 Angular 程序。Observable 是一種趨勢。HTTP 客戶端就需要 RxJS,所以我們必須採用額外的步驟開啟 RxJS Observables。
事實上可以只載入需要的部分,不過先全引入吧!
import rxjs-operator
into app.component.ts
// Add all operators to Observable
import 'rxjs/Rx';
Angular Http client (客戶端) 和伺服器通訊是藉由熟習的 Http 要求/回應 (request/response) 協議。而且 Http
client 應該是 Angular 中關於 Http 最常用到的函式庫了。
使用 Http client 的時候,應該將將服務註冊為依賴注入系統中。
直接看範例
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class HttpClientService {
constructor (private http: Http) {}
get(url: string, optionHeader?: {[header: string]: string}): Observable<Response> {
let headers = new Headers();
// set option header
for(let header in optionHeader) {
let value = optionHeader[header];
headers.append(header, value);
}
return this.http.get(url, {headers: headers,})
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: Response | any) {
// In a real world app, we might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
首先先注入 http
進入 HttpClientService
constructor (private http: Http) {}
url
就是要 call 的 API 位置。http.get
方法返回的是一個 HTTP 響應 Observable 對象,由 RxJS 庫提供,map()
也是 RxJS 的一個操作符。
map()函數中,我們會將提取數據映射到 this.extractData
函數
private extractData(res: Response) {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body = res.json();
return body.data || { };
}
Response 不能直接用,要先除錯,並將資料轉換成 json 給程式使用。
getData() {
this.HttpClientService.get(url:string)
.subscribe(
data => this.data = data,
error => this.errorMessage = <any>error
);
}
方法也大同小異
post(url: string, body: any, optionHeader?: {[header: string]: string}): Observable<Response> {
let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'});
// set option header
for(let header in optionHeader) {
let value = optionHeader[header];
headers.append(header, value);
}
let newUrl = this.globalVariablesService.apiURL + url;
return this.http.post(newUrl, body, {
headers: headers,
}).map(this.extractData)
.catch(this.handleError);
}
事實上我們也可以這樣寫
export class HttpClientService {
...
get(url: string, optionHeader?: {[header: string]: string}): Observable<Response> {
let headers = new Headers();
// set option header
for(let header in optionHeader) {
let value = optionHeader[header];
headers.append(header, value);
}
return this.http.get(url, {
headers: headers,
}).catch((res: Response) => this.handleError(res));
}
...
}
當其他函數要調用 get
方法時注入,且先不處理成功的資料。
getData(): void {
let url = 'htts://...'
this.httpClientService.get(url)
.subscribe(
(res : Response) => {
let data = res.json();
},
(err: any) => {
console.log('err:',err);
}
);
}
前一種寫法適合寫明確回傳東西的服務,後者適合寫通用型,可以接受任何資料,最後在轉換。不管哪一種寫法都是將 http
方法和要最後處理的工作做區隔,發生錯誤時可以區分是 http
出錯還是 getData()
出錯,取到資料後可以再拿來做其他事情。簡單來說就是將程式做層級化,邏輯根管理都比較容易。
當然除了 Angular 官方提供的方法,AJAX 還是一樣受大家愛戴。
沒什麼技術好說的,一樣是異步,而且記得要引入 jQuery。比較麻煩的是 TSlint 看不懂 $
,所以可以很作弊的這樣做。declare var $:any;
放在 ts 最前面。
$.ajax({
url: url,
type: 'POST',
data: {'data':JSON.stringify(json)},
success: function(data: any) {
console.log(data);
},
error: function(XMLHttpRequest: any, textStatus: any, errorThrown: any) {
console.log(errorThrown);
}
});
AJAX 就不多說甚麼了,總之也是個方法。