# 鋪墊
? Axios 是一個基于 Promise 的 HTTP 庫,它的瀏覽器支持性良好,是Vue主推請求異步的方法;它支持多種請求的簡寫和請求參數(shù)的配置逞盆,也支持使用自定義配置新建一個axios實例,舉例如下
const request = axios.create({
baseURL: 'https://domain-name.com/api/'
timeout: 8000
})
? 其中松申,create()
方法中是自定義的初始化配置參數(shù)云芦。初始化數(shù)據(jù)除此之外,通常還會設(shè)置攔截器贸桶,實現(xiàn)header
參數(shù)添加舅逸,錯誤打印及HTTP碼的統(tǒng)一處理等,如下
// 添加請求攔截器
axios.interceptors.request.use(function (config) {
if (store.getters.token) {
config.headers.common['X-Token'] = getToken()
config.headers.common['X-Requested-With'] = 'XMLHttpRequest'
config.headers.common['Access-Control-Allow-Origin'] = '*'
config.params = {
_t: Date.parse(new Date()) / 1000,
...config.params
}
return config;
}, function (error) {
console.log('request error:', error)
return Promise.reject(error);
});
// 添加響應(yīng)攔截器
axios.interceptors.response.use(function (response) {
if (res.code !== 0) {
console.log(`請求錯誤: ${res.request.responseURL} \nCode: ${res.data.code}`);
}
return response;
}, function (error) { // request timeout is an error
let msg = 'UnknownError'
const res = error.response
if (res) {
msg = errorMessage.find((t) => t.code === res.status).msg || msg
if (res.status === 401 || res.status === 403) {
window.location.href = res.data.redirect_url
} else {
Message.error(msg)
}
} else {
Message.error(error.message)
}
return Promise.reject(error);
});
// HTTP CODE及錯誤提示
const errorMessage = [
{ code: 400, msg: '請求錯誤' },
{ code: 401, msg: '未授權(quán)皇筛,請登錄' },
{ code: 403, msg: '拒絕訪問' },
{ code: 404, msg: '請求地址出錯' },
{ code: 408, msg: '請求超時' },
{ code: 500, msg: '服務(wù)器內(nèi)部錯誤' },
{ code: 501, msg: '服務(wù)未實現(xiàn)' },
{ code: 502, msg: '網(wǎng)關(guān)錯誤' },
{ code: 503, msg: '服務(wù)不可用' },
{ code: 504, msg: '網(wǎng)關(guān)超時' },
{ code: 505, msg: 'HTTP版本不受支持' }
]
? 一般我們將它封裝為request.js
文件并暴露出接口以便外部使用琉历。在外部調(diào)用的過程中,如遇到不符合要求或需要新增的config
參數(shù)是允許覆蓋和新增的水醋,編寫如下
import request from '@/request'
export function queryUserInfo(data) {
return request({
url: '/users/userInfo',
method: 'get',
params: data
})
}
? 這里旗笔,request方法中的配置參數(shù)會按一定的規(guī)則merge
到最終的Axios請求中。
?
# 取消重復(fù)的請求
? 先來回顧一下官網(wǎng)講解的內(nèi)容
Axios使用
cancel token
取消請求拄踪,它基于cancelable promises proposal實現(xiàn)蝇恶,目前該API還處在第一階段
? 官網(wǎng)介紹了取消請求的兩種辦法:
1. 可以利用CancelToken
工廠函數(shù)創(chuàng)建cancel token
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// get 方法使用案例
axios.get('user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message)
} else {
// TODO: handle error
}
})
// post 使用案例
axios.post('/user/12345', {
name: 'name what'
}, {
cancelToken: source.token
})
// 執(zhí)行取消請求操作
source.cancel(‘請求已取消’)
2. 傳遞executor
函數(shù)到CancelToken
的夠造函數(shù)來創(chuàng)建cancel token
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
cancel = c
})
})
// 執(zhí)行取消請求操作
cancel()
? 并且官網(wǎng)特意強調(diào)了,不同請求可以定義同一個取消請求的方法名宫蛆,來批量取消多個請求艘包。
# 案例
? 結(jié)合【鋪墊】內(nèi)容的猛,筆者使用方法2來舉例實現(xiàn)取消請求耀盗,還是拿上方的請求為例,做如下修改
import request from '@/utils/request'
import axios from 'axios'
export function queryUserInfo(data, _this) {
const CancelToken= axios.CancelToken
return request({
url: '/users/userInfo',
method: 'get',
params: data,
cancelToken: new CancelToken(function executor(c) {
_this.cancelAjax = c
})
})
}
? 以上我們利用executor
生成了取消函數(shù)卦尊,并賦值給外部真實請求傳入的環(huán)境中叛拷,形參_this
的實參為Vue的this
變量。
// 選擇人員列表查詢
getUserInfo() {
if (typeof this.cancelAjax === 'function') {
this.cancelAjax()
}
this.allUsers.loading = true
queryUserInfo({ userId: '20192430139' }, this).then(res => {
if (res.code === 1) {
this.userInfo.data = res.data
this.allUsers.loading = false
} else {
this.$message.error(res.msg || 'get userInfo error')
}
})
}
? 思路就是岂却,當請求發(fā)起時cancelToken
會派發(fā)函數(shù)給data中的cancelAjax
忿薇,可以利用數(shù)據(jù)類型偵查是否請求正在發(fā)生裙椭。cancelAjax
在頁面初始化時定義為null
即可
<template>
</template>
<script>
export default {
data() {
return {
cancelAjax: null
}
}
}
</script>
? 至此,已實現(xiàn)了基本邏輯署浩,在頁面連續(xù)出發(fā)請求時揉燃,可以看到請求的取消表現(xiàn)
?
# 通過攔截器實現(xiàn)統(tǒng)一處理
? 修改你的請求二次封裝文件,大致如下
// request.js
import axios from 'axios'
const cancelToken = {} // 數(shù)組用于儲存每個請求的取消函數(shù)和請求標識
const CancelToken = axios.CancelToken
// 取消被多次發(fā)起的請求筋栋,保留最后一個
const cancelAjax = (type, config) => {
const key = getUrlKey(config)
if (type === 'check') {
if (!cancelToken[key]) {
config.cancelToken = new CancelToken((c) => {
cancelToken[key] = c
})
} else {
cancelToken[key]()
}
} else if (type === 'remove') {
delete cancelToken[key]
}
}
// 允許多次重復(fù)調(diào)用的API白名單
const whiteList = []
// request interceptor
service.interceptors.request.use((config) => {
if (!whiteList.includes(config.url)) {
cancelAjax('check', config)
}
return config
}, err => {
console.log('request intercepter err:' + err) // 打印錯誤
return Promise.reject(err)
})
// response interceptor
service.interceptors.response.use(
async response => {
cancelAjax('remove', response.config)
const res = response.data
...
},
err => {
console.log('response intercepter err: ' + err) // 打印錯誤
...
return Promise.reject(err)
}
)