App每每都有緩存功能,例如常見的新聞類應用,若是你關閉網絡,你上次打開App加載的數據還在,只是不能加載新的數據了。
個人博客bougieblog.cn,歡迎前來尬聊。javascript
若是你fetch數據的頁面有多個,不集中處理的話每一個頁面都要單獨進行緩存處理。那麼,如何對http請求進行集中處理?
在WebApp中常見的作法就是將請求放在action
裏面,例如Vuex
和Redux
。可是在業務邏輯較少的App中,咱們每每可能不須要Redux
。這時就須要咱們本身對集中請求進行封裝。html
AsyncStorage只能存取字符串,咱們需封裝一下,讓它能存取json
:java
import { AsyncStorage } from 'react-native' class Storage { set({key, val}) { return AsyncStorage.setItem(key, JSON.stringify(val)) } get(key) { return AsyncStorage.getItem(key).then(val => { return JSON.parse(val) }) } remove(key) { return AsyncStorage.removeItem(key) } clear() { return AsyncStorage.clear() } } export default new Storage()
命名爲storage.js
react
在網絡故障時獲取storage裏的內容,網絡良好時更新storage。ios
import axios from 'axios' import storage from './storage' import apiList from './apiList' import {NetInfo, ToastAndroid} from 'react-native' /** * @param {String} api 接口名稱 * @param {Object} [replace={}] 替換url中的{}包裹的參數 * @param {Object} [data={}] 傳給服務端的數據 * @param {Object} [headers={}] http請求頭參數 * @return {Promise} 返回promise */ const $http = async ({api, replace, data, headers}) => { let regExp = /\{ *([\w_\-]+) *\}/g, url = apiList[api].url, replaceList = url.match(regExp) if(replaceList) { replaceList.forEach(i => { let key = i.slice(1, i.length - 1) url = url.replace(i, replace[key]) }) } let netStatu = await NetInfo.getConnectionInfo() let result if(['none', 'unknown'].includes(netStatu.type)) { ToastAndroid.show('請檢查您的網絡鏈接', ToastAndroid.SHORT) result = await storage.get(api) || null } else { try { let {data} = await axios({ method: apiList[api].method, url: url, data: data, headers: headers }) result = data } catch(err) { ToastAndroid.show(err.message, ToastAndroid.SHORT) result = await storage.get(api) || null } await storage.set({ key: api, val: result }) } return result } export default $http
命名爲service.js
json
爲標示請求惟一性,咱們需給每一個請求取一個名稱:axios
export default { GET_NEWS_LIST: { url: '/my/news?pageNum={pageNum}&pageSize={pageSize}', method: 'get' } }
命名爲apiList.js
react-native
咱們能夠模仿一下Vuex
或Redux
的action:api
import $http from './service' export async function getNewsList(pageNum, pageSize) { return await $http({ api: 'GET_NEWS_LIST', replace: { pageNum, pageSize } }) }
命名爲serviceAction.js
調用:promise
import {getNewsList} from './serviceAction' // ... async componentDidMount() { let newsList = await getNewsList(1) this.setState({ newsList }) } // ...