任何項目,只要支持axios,那麼你只要把我現在封裝的服務整個文件夾考過去即可。這個原本是我封裝在vue裏的,但是有一天公司突然來一個緊急的H5微信分享活動的項目,我當時用react搭建(zepto+node搭建其實最好)也是爲了挑戰一下自己,畢竟只有三天時間。所以當我把很多vue裏封裝的東西直接拷到react項目時,居然發現一點毛病都沒有,我瞬間覺得自己好機智,之前沒有怕浪費時間隨便封裝。其中包括axios服務,拷到react項目毫無毛病的就跑起來,surprise!!!
文件夾結構:
- 原理就是獲取導航欄地址然後正則匹配字符串
// config.js
let env = ''
if ((/env=online/.test(window.location.href))) {
env = 'online'
} else if ((/env=dev/.test(window.location.href))) {
env = 'dev'
} else {
env = 'dev' // 默認環境
}
const SERVER_URL = {
online: { // 正式環境
SERVER_URL1: '',
SERVER_URL2: '',
SERVER_URL3: ''
},
dev: { // 測試環境
SERVER_URL1: '',
SERVER_URL2: '',
SERVER_URL3: ''
}
}
export default SERVER_URL[env]
env的功能是爲了方便地址欄直接切換環境,開發時我們用的是後臺的測試接口,上線時用的是線上接口,栗子:
- 測試環境:http://0.0.0.0:8082/#/entry/entryIndex
- 切換到
- 正式環境:http://0.0.0.0:8082/?env=online/#/entry/entryIndex
- 封裝axios實例
- 配置響應攔截/請求攔截
- 響應攔截這兒主要就是處理一下後端傳的code值,因爲後臺小哥哥老是這個傳字符串那個傳數字,心塞塞~
- 併發請求
-
axios.all 是axios的靜態方法,不是實例上的方法,所以要在實例上做操作
-
// interApi.js
import axios from 'axios'
import config from './config'
// 配置 axios,並生成實例
const creatAxios1 = axios.create({
baseURL: config.SERVER_URL1,
withCredentials: true
})
// 攔截器配置
creatAxios1.interceptors.request.use(configData => { // 請求攔截 在發送請求之前做些什麼
// 請求成功做的事情 configData 中包含:url、method等信息
return configData
}, error => { // 請求失敗做的事情
return Promise.reject(error)
})
creatAxios1.interceptors.response.use(response => { // 響應攔截 對響應數據做點什麼
// 響應成功做的事情
response.data.code = Number(response.data.code) // 將接口返回的狀態值 code 處理爲數字
return response
}, error => { // 響應失敗做的事情
return Promise.reject(error)
})
function sendAll (arr) { // 順序和請求發送的順序相同,使用 axios.spread 分割成多個單獨的響應對象
if (Object.prototype.toString.call(arr) === '[object Array]') {
return axios.all(arr).then(axios.spread(function (...res) { // axios.all 是axios的靜態方法,不是實例上的方法
// 請求全部都執行完成
return Promise.resolve(res)
}))
} else {
const error = new Error('參數錯誤!')
try {
throw error
} catch (e) {
// console.log(e)
}
}
}
export default {
creatAxios1,
sendAll
}
- 暴露 API 方法:get請求 post請求 併發請求
// extendsApi.js
/* eslint-disable no-useless-constructor */
import api from './interApi'
import qs from 'qs'
import config from './config'
function _apiFn (baseUrl) { // 該方法對外不可見
if (baseUrl === 'service2') {
api.creatAxios1.defaults.baseURL = config.SERVER_URL2 // 改變 axios 實例的 baseURL
} else if (baseUrl === 'service3') {
api.creatAxios1.defaults.baseURL = config.SERVER_URL3
} else {
api.creatAxios1.defaults.baseURL = config.SERVER_URL1
}
}
class axiosApi {
constructor () {
}
sendGet (url, params = {}, baseUrl) { // get 請求
if (Object.prototype.toString.call(params) === '[object Object]') {
_apiFn(baseUrl)
return api.creatAxios1.get(url, {params: params})
} else {
const error = new Error('參數錯誤!')
try {
throw error
} catch (e) {
// console.log(e)
}
}
}
sendPost (url, params = {}, baseUrl) { // post 請求
if (Object.prototype.toString.call(params) === '[object Object]') {
_apiFn(baseUrl)
return api.creatAxios1.post(url, qs.stringify(params))
} else {
const error = new Error('參數錯誤!')
try {
throw error
} catch (e) {
// console.log(e)
}
}
}
/**
* 併發請求,同時發送多個請求,使用栗子:src/views/infoEntry/dragCard/dragCardService.js
* 順序和請求發送的順序相同
* @param {arr: [請求1,請求2...]}
*/
sendAll (arr) { // 併發請求
return new Promise((resolve, reject) => {
api.sendAll(arr).then(res => {
return resolve(res)
})
})
}
}
export default axiosApi
- 公共服務使用方法
// index.js
// commit API
import extendsApi from './extendsApi'
class AllServiceApi extends extendsApi {
constructor () {
super()
this.demoUrl = ''
}
demoGet (params) {
return this.sendGet(this.demoUrl, params).then(res => {
return res.data
})
}
}
export default new AllServiceApi()
- 組件中的使用方法
// commit API
import extendsApi from 'services/extendsApi'
class LoginServiceApi extends extendsApi {
constructor () {
super()
this.demoUrl = ''
}
demoGet (params) {
return this.sendGet(this.demoUrl, params).then(res => {
return res.data
})
}
}
export default new LoginServiceApi()
全局公共服務/組件的私有服務,如上封裝以及使用即可。