angular4自身提供的請求方法是用Observable來實現的。用的是觀察者模式,我的認爲這用來寫請求是很是方便的。html
一個項目裏會有很是多的不一樣的請求,可是其實每一個請求都會有些共性。好比:每一個請求都要傳Authorization,好比每一個請求都要先判斷後臺返回的status字段爲200時纔是請求成功,後臺正真返回的數據在data字段裏,好比對於錯誤信息的處理都是同樣的......等等。typescript
因此咱們須要封裝出一個請求,去統一處理這些問題,從而保證組件裏調用請求方法的時候收到的值都是能夠直接拿來用的,幾乎不用再寫些重複的代碼。json
固然是越少重複的代碼越好,咱們就是想偷懶!!!! api
首先先新建一個請求的service,文件名爲:request.service.ts。而後跟着我來虛擬需求,一步一步的慢慢來完善這個service。數組
1.請求方式爲get。安全
2.默認的請求超時時間爲3秒,可傳入別的超時時間。angular4
3.後臺返回的成功的json爲這樣:this
{ "status": 200, "data" : ... }
錯誤時這樣:url
{ "status": 201, "msg" : "用戶名或密碼錯誤" }
request.service.tsspa
/** ******************************************************************************************** * @App: test * @author: isiico * @type: service * @src: services/request.service.ts * * @descriptions: * 請求的服務 * ******************************************************************************************** */ // Angular Core import {Injectable} from '@angular/core'; import {HttpClient} from '@angular/common/http'; // rxjs import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/timeout'; import 'rxjs/add/observable/throw'; @Injectable() export class RequestService { private setTimeout = 3000; // 默認的超時時間 constructor(private http:HttpClient) { } /** 獲取數據 * param: url string 必填,請求的url * time number 可不填,請求的超時時間,如不填,默認爲setTimeout * return: Observable HttpClient的get請求,請求完成後返回的值類型是any **/ public getData(url, time = this.setTimeout):Observable<any> { let thiUrl = url; // 用到的url let thisTime = time; // 用到的超時時間 return this.http.get(thiUrl) .timeout(thisTime) .map(res => this.resFun(res)); } /** 返回數據的處理 * param: data any 必填,須要處理的數據 * return: res any 返回處理後的值 **/ private resFun(data:any):any { let thisData:any = data; // 須要處理的值 let res:any; // 最終值 // 當status爲200時 if (thisData['status'] == 200) { res = thisData['data']; // 給最終值賦值 } else { // 當status不爲200時 let err = thisData['msg']; // 錯誤信息 throw new Error(err); // 拋出錯誤 } return res; // 返回最終值 } }
1.爲了安全,後臺要求請求的頭須要加上Authorization參數。
2.當請求失敗(如404,500這種)時,處理好錯誤信息,最後的錯誤信息要像 實現A 裏同樣,是能夠直接用的字符串類型的錯誤信息。
request.service.ts (只展現新增的代碼,完整代碼後面有)
import 'rxjs/add/operator/catch'; @Injectable() export class RequestService { /** 添加Authorization的屬性 */ private addAuthorization(options:any):void { options['headers'] = { 'Authorization': '1drf5dg4d7s4w7z', }; } /** 獲取數據 * param: url string 必填,請求的url * time number 可不填,請求的超時時間,如不填,默認爲setTimeout * return: Observable HttpClient的get請求,請求完成後返回的值類型是any **/ public getData(url, time = this.setTimeout):Observable<any> { let thiUrl = url; // 用到的url let options = {}; // 請求的設置 let thisTime = time; // 用到的超時時間 this.addAuthorization(options); // 請求頭裏添加Authorization參數 return this.http.get(thiUrl, options) .timeout(thisTime) .catch(this.httpErrorFun) // 處理錯誤信息(必須放在timeout和map之間) .map(res => this.resFun(res)); } /** 對請求錯誤信息的處理 * param: err any 必填,須要處理的錯誤信息 * return: Observable.throw Observable<string> string:處理後顯示的錯誤文字 **/ public httpErrorFun(err:any):Observable<string> { let res:string = ''; // 處理後的結果 let data:any = err; // 須要處理的值 /** 後臺有返回錯誤信息時 */ if (data.hasOwnProperty('error') && data.hasOwnProperty('message')) { res = data.message; /** 後臺沒有返回錯誤信息只有錯誤名時 */ } else if (data.hasOwnProperty('name')) { let errName = data.name; /** 請求超時 */ if (errName == 'TimeoutError') { res = '對不起,請求超時了'; } /** 後臺返回未受權時 */ } else if (data == "Unauthorization") { res = '您沒有權限,請從新登陸'; } else { res = "哎呀,不知道是啥錯誤~~"; } return Observable.throw(res); } }
request.service.ts
/** ******************************************************************************************** * @App: test * @author: isiico * @type: service * @src: services/request.service.ts * * @descriptions: * 請求的服務 * ******************************************************************************************** */ // Angular Core import {Injectable} from '@angular/core'; import {HttpClient} from '@angular/common/http'; // rxjs import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/timeout'; import 'rxjs/add/observable/throw'; import 'rxjs/add/operator/catch'; @Injectable() export class RequestService { private setTimeout:number = 3000; // 默認的超時時間 constructor(private http:HttpClient) { } /** 添加Authorization的屬性 */ private addAuthorization(options:any):void { options['headers'] = { 'Authorization': '1drf5dg4d7s4w7z', }; } /** 獲取數據 * param: url string 必填,請求的url * time number 可不填,請求的超時時間,如不填,默認爲setTimeout * return: Observable HttpClient的get請求,請求完成後返回的值類型是any **/ public getData(url, time = this.setTimeout):Observable<any> { let thiUrl = url; // 用到的url let options = {}; // 請求的設置 let thisTime = time; // 用到的超時時間 this.addAuthorization(options); // 請求頭裏添加Authorization參數 return this.http.get(thiUrl, options) .timeout(thisTime) .catch(this.httpErrorFun) // 處理錯誤信息(必須放在timeout和map之間) .map(res => this.resFun(res)); } /** 返回數據的處理 * param: data any 必填,須要處理的數據 * return: res any 返回處理後的值 **/ private resFun(data:any):any { let thisData:any = data; // 須要處理的值 let res:any; // 最終值 // 當status爲200時 if (thisData['status'] == 200) { res = thisData['data']; // 給最終值賦值 } else { // 當status不爲200時 let err = thisData['msg']; // 錯誤信息 throw new Error(err); // 拋出錯誤 } return res; // 返回最終值 } /** 對請求錯誤信息的處理 * param: err any 必填,須要處理的錯誤信息 * return: Observable.throw Observable<string> string:處理後顯示的錯誤文字 **/ public httpErrorFun(err:any):Observable<string> { let res:string = ''; // 處理後的結果 let data:any = err; // 須要處理的值 /** 後臺有返回錯誤信息時 */ if (data.hasOwnProperty('error') && data.hasOwnProperty('message')) { res = data.message; /** 後臺沒有返回錯誤信息只有錯誤名時 */ } else if (data.hasOwnProperty('name')) { let errName = data.name; /** 請求超時 */ if (errName == 'TimeoutError') { res = '對不起,請求超時了'; } /** 後臺返回未受權時 */ } else if (data == "Unauthorization") { res = '您沒有權限,請從新登陸'; } else { res = "哎呀,不知道是啥錯誤~~"; } return Observable.throw(res); } }
至此,咱們已經完成了一個知足基本需求的,能夠公共使用的請求服務,接下來咱們來看怎麼在組件內調用。
咱們有個叫list的組件,要調用get請求,請求成功顯示數據,請求失敗,顯示錯誤信息。
list.component.ts
/** ******************************************************************************************** * @App: test * @author: isiico * @type: component * @src: components/list.component.ts * * @descriptions: * list組件 * ******************************************************************************************** */ // Angular Core import { Component, OnInit } from '@angular/core'; // Services import { RequestService } from "../services/request.service"; @Component({ moduleId: module.id, templateUrl: 'list.component.html' }) export class ListComponent implements OnInit { listApi = '/assets/mock-data/list.json'; // 列表的api地址 list:Array<any>; // 列表數據(類型爲數組) listErrMsg: string = ''; // 列表請求的錯誤信息 constructor(private req: RequestService) { } /** 獲取list */ getList(){ this.listErrMsg = ''; // 清空錯誤信息 // 發送請求 this.req.getData(this.cabinetListApi) .subscribe( res=>{ // 請求成功 this.cabinets = []; this.cabinets = res; },err=>{ // 請求失敗 this.cabinets = []; this.listErrMsg = err; }) } ngOnInit() { this.getList(); } }
頁面的顯示本身去完成吧!