在React Native開發過程當中,幾乎全部的app都須要使用到Http請求,因此fetch的封裝必不可少,因爲不一樣app的請求參數,解析規則,token機制等徹底不同,因此在大多數App開發中,先後臺Http請求的實現都是開發者本身封裝的。react
封裝一個先後臺Http請求實現須要多久?git
可能有人回答是1小時,也有三、5小時甚至更長時間的,或者也有說先這樣封裝個大概,等到需求不知足的時候再改。github
花費1小時的時間不必定短,花費三、5的時間也不必定算長,具體要看先後臺交互的複雜程度與開發者對交互實現的封裝程度。npm
那這裏咱們就引出了一個問題了,咱們一般說的app的Http請求【封裝】,到底封裝的是什麼,咱們須要作哪些工做,能使用得app的接口請求更簡單,易用且有較高的靈活性?在我看來這個「封裝」主要分兩個部分:json
數據交換 層面的封裝,即:react-native
從投入的時間上來看:
第一部分基本上要花掉開發者80%以上的時間來封裝
第二部分須要消耗的時間可能不足20% 【以此推算,按上面1個小時的封裝時間,用在邏輯封裝部分的時間也就12分鐘左右】api
咱們再回頭看一下,第一部分的【數據交換】封裝是否涉及到具體業務邏輯呢?答案是:沒有。服務器
既然沒有咱們爲何不把第一部分的封裝交給第三方框架呢,咱們只須要作第二部分的封裝多省事,有這樣第三方框架麼?數據結構
答案是:有的,react-native-easy-app 就能夠實現【先後臺數據交換】層面的封裝,經過這個開源庫,咱們就只須要實現涉及【App業務邏輯】層面的封裝便可。app
爲驗證 react-native-easy-app 的實用性,在這裏咱們先來構想一個業務邏輯層面封裝的需求:
請求接口的公共headers參數有:
請求接口的公共params參數有:
後臺返回的數據結構示例以下:
{ data: {}, successful:1, msg: 'request msg', code: 'xxx'}
請求狀態碼爲503的時候表示accessToken過時,accessToken過時的狀況下,須要從新獲取新的accessToken並刷新因accessToken過時致使請求失敗的接口
對於以上業務邏輯層面的需求,看看經過 react-native-easy-app 咱們能夠怎麼作。
XHttpConfig().initHttpLogOn(true) .initHeaderSetFunc((headers) => { headers['model'] = 'xiao mi'; headers['version'] = '1.0.0'; headers['platform'] = Platform.OS; headers['channelCode'] = 'channelOfficial'; if (isLogin()) { headers['customerId'] = RNStorage.customerId; headers['accessToken'] = RNStorage.accessToken; headers['refreshToken'] = RNStorage.refreshToken; } }) .initParamSetFunc(params => { if (isLogin()) { params['customerId'] = RNStorage.customerId; } }) .initParseDataFunc((result, request, callback) => { let {success, json, message, status, response} = result; if (status === 503) {// accessToken過時標記 this.refreshToken(request, callback); } else { let {data, successful, msg, code} = json; callback(success && successful === 1, data || {}, msg || message, code, response); } });
accessToken從新請求的實現及對失敗接口的刷新:
refreshToken = (request, callback) => { if (global.hasQueryToken) { global.tokenExpiredList.push({request, callback}); } else { global.hasQueryToken = true; global.tokenExpiredList = [{request, callback}]; const refreshUrl = `${RNStorage.baseUrl}api/refreshToken?refreshToken=${RNStorage.refreshToken}`; fetch(refreshUrl).then(resp => { resp.json().then(({successful, data: {accessToken}}) => { if (successful === 1) {// 獲取到新的accessToken RNStorage.accessToken = accessToken; global.tokenExpiredList.map(({request, callback}) => { request.resendRequest(request, callback); }); global.tokenExpiredList = []; } else { console.log('Token 過時,退出登陸'); } }); }).catch(err => { console.log('Token 過時,退出登陸'); }).finally(() => { global.hasQueryToken = false; }); } };
就這樣對當前構想的app的邏輯層面的封裝就實現了(實現上面的代碼約70行,也許要超過20分鐘 ,但相較於之前從零開的封裝,是否是節約了大量的時間呢?)是否是清晰明瞭。固然,這只是代碼片斷,沒有實際操做,就沒辦法證實上面的代碼實現是實際有效的。
爲了演示,先用 react native init HttpTestDemo
建立一個RN項目:示例項目:HttpTestDemo 修改並刪除沒必要要的佈局或資源,結果以下:
假定有三個接口,分別爲 api/login、api/userInfo 、api/refreshToken (爲了省事,接口都以json文件替代)
https://react-native-fast-app.oss-cn-beijing.aliyuncs.com/api/login
https://react-native-fast-app.oss-cn-beijing.aliyuncs.com/api/userInfo
https://react-native-fast-app.oss-cn-beijing.aliyuncs.com/api/refreshToken
按 react-native-fast-app 的說明文檔,安裝庫:npm install react-native-fast-app --save
export const RNStorage = {// 持久化數據列表 customerId: undefined,//客戶ID accessToken: undefined,//OAuth2.0 accessToken refreshToken: undefined,//OAuth2.0 refreshToken baseUrl: undefined, userInfo: undefined, hasLogin: false, };
3.在頁面的構造方法時調用 RNStorage的初始化操做;初始化完成以後,調用Http請求XHttpConfig的【業務邏輯】層初始化方法,這樣就完成了,如今就能夠調用接口了。
import { XHttp } from 'react-native-easy-app'; login = () => { let params = {userName: 'zhangsan', userPass: '123456a'}; XHttp().url('api/login').param(params).formEncoded().get((success, json, message, status, resonse) => { if (success) { if (resonse.headers && resonse.headers.map) { RNStorage.accessToken = resonse.headers.map['x-oss-meta-accesstoken']; RNStorage.refreshToken = resonse.headers.map['x-oss-meta-refreshtoken']; } RNStorage.customerId = json.customerId; RNStorage.hasLogin = true; this.setState({data: JSON.stringify(json)}); } else { console.log('失敗', message); } }); };
調用接口,經過框架自帶的日誌功能,能夠看到,該拼的參數都拼接了,從header中也獲取到了token
import { XHttp } from 'react-native-easy-app'; queryUserInfo = () => { XHttp().url('api/userInfo').formJson().get((success, json, message) => { if (success) { RNStorage.userInfo = json; this.setState({data: JSON.stringify(json)}); } else { console.log('失敗', message); } }); };
調用接口,經過框架自帶的日誌功能,能夠看到accessToken、refreshToken也正確的拼接了。
因爲沒有合適的服務器,token過時的狀況就不演示了,只要請求refreshToken的接口正常請求就不會有問題。
至此一個完整的App 【業務邏輯】層面的封裝就徹底實現了,從Http請求的配置到,refreshToken的從新請求到刷新失敗接口,一共大概只用了70行代碼左右,是否是相較於以前從零開始的fetch封裝簡單容易多了,節約了大量的封裝時間呢?
擔憂框架的靈活性?請參考 react-native-easy-app 詳解與使用之(二) fetch 而且react-native-easy-app 開源庫並不僅有Http請求的封裝,還有更多功能,有興趣的同窗能夠查看此欄目的其它文章,你確定會有更多收穫。
當前示例項目連接:HttpTestDemo