咱們在使用axios進行異步操做時,可能會遇到如下狀況:css
axios.post(url, data).then(res=>{}).catch(err=>{})
複製代碼
這裏咱們發現咱們每一次寫的時候,都須要寫.catch(err=>{}),會形成代碼的冗餘// 添加請求攔截器
axios.interceptors.request.use(function (config) {
// 在發送請求以前作些什麼
return config;
}, function (error) {
// 對請求錯誤作些什麼
return Promise.reject(error);
});
// 添加響應攔截器
axios.interceptors.response.use(function (response) {
// 對響應數據作點什麼
return response;
}, function (error) {
// 對響應錯誤作點什麼
return Promise.reject(error);
});
複製代碼
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函數接收一個 cancel 函數做爲參數
cancel = c;
})
});
// 取消請求
cancel();
複製代碼
axios.js
設置一個cancelFlag做爲標誌符,默認爲true,在請求攔截器時,判斷若是cancelFlag爲true,就能夠發送請求,且將cancelFlag設爲false。當cancelFlag爲false,就取消請求。在響應攔截器中再將cancelFlag設爲true。說明只用當一個請求發送且收到響應後,才能夠發送另外一個請求。這裏存在的問題:cancelFlag是全局變量,這樣多頁面多個接口請求時,互相會有影響這裏的解決辦法就是在axios.js中構建構造函數,這樣可讓cancelFlag私有化,可是這樣的方式會致使佔有大量內存。
參考同事寫的代碼(版本二),我以爲很是的有道理。並且比較簡單。
版本1、使用cancelFlag全局變量判斷vue
import Vue from 'vue'
import axios from 'axios'
import {Indicator} from 'mint-ui'
Vue.component(Indicator)
let CancelToken = axios.CancelToken //取消請求
let cancelFlag = true
//設置公共部分,請求頭和超時時間
axios.defaults.headers = {
'X-Requested-With': 'XMLHttpRequest'
}
axios.defaults.timeout = 20000
//在請求攔截器時
axios.interceptors.request.use(config => {
if (cancelFlag) {
cancelFlag = false
Indicator.open()
} else {
cancelToken: new CancelToken (c => {
cancel = c
})
cancel()
}
return config
}, error => {
return Promise.reject(error)
})
axios.interceptors.response.use(config => {
cancelFlag = true
Indicator.close()
return config
}, error => {
//
})
複製代碼
版本2、異步請求時,帶上一個參數requestName。
這裏一開始的疑惑是,當請求a帶上參數requestName後,發送屢次請求,判斷axios[requestName]和axios[requestName].cancel存在時,會作取消處理。那發送成功後,再點擊時,axios[requestName]和axios[requestName].cancel仍是會存在啊。這樣仍是會執行axios[requestName].cancel()。
這裏是由於當上一次請求發送成功後,其axios[requestName].cancel這個方法已經失效,即便執行了這個方法也不起做用。axios[requestName].cancel的值永遠是上一次的請求的取消回調。當上一次請求成功後,該回調會失效。ios
axios.interceptors.request.use(config => {
let requestName = config.data.requestName
if (requestName) {
if (axios[requestName] && axios[requestName].cancel) {
axios[requestName].cancel()
}
config.cancelToken = new CancelToken (c => {
axios[requestName] = {}
axios[requestName].cancel = c
})
}
return config
}, error => {
return Promise.reject(error)
})
複製代碼
響應的錯誤處理封裝git
axios.interceptors.response.use(config => {
Indicator.close()
return config
}, error => {
cancelFlag = true
Indicator.close()
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '錯誤請求'
break;
case 401:
error.message = '未受權,請從新登陸'
break;
case 403:
error.message = '拒絕訪問'
break;
case 404:
error.message = '請求錯誤,未找到該資源'
break;
case 405:
error.message = '請求方法未容許'
break;
case 408:
error.message = '請求超時'
break;
case 500:
error.message = '服務器端出錯'
break;
case 501:
error.message = '網絡未實現'
break;
case 502:
error.message = '網絡錯誤'
break;
case 503:
error.message = '服務不可用'
break;
case 504:
error.message = '網絡超時'
break;
case 505:
error.message = 'http版本不支持該請求'
break;
default:
error.message = `鏈接錯誤${error.response.status}`
}
} else {
error.message = "鏈接到服務器失敗"
}
return Promise.reject(error.message)
})
複製代碼
http.js(封裝了post和get請求)
在axios.js文件裏對響應攔截器作了判斷error.response.status的值的處理,根據不一樣的狀態碼返回不一樣的error說明。在http.js文件裏post和get函數的參數爲三個,第三個參數error就是出現錯誤時的文案。使用該api能夠本身設置該文案,若是不傳這個參數,那麼就返回axios.js設置的error文案github
import Vue from 'vue'
import axios from './axios'
import 'mint-ui/lib/style.css';
import {Toast} from 'mint-ui'
Vue.component(Toast)
export function post (url, data, error) {
return new Promise((resolve, reject) => {
axios.post(url, data).then(res => {
resolve(res)
}, err => {
err = error ? error : err
Toast({
message: err,
duration: 500
})
})
})
}
export function get (url, data, error) {
return new Promise((resolve, reject) => {
axios.post(url, {
data: data
}).then(res => {
resolve(res)
}, err => {
err = error ? error : err
Toast({
message: err,
duration: 500
})
})
})
}
複製代碼
1)在main.js引入文件axios
import axios from '../utils/axios.js'
import {post, get} from '../utils/http.js'
Vue.prototype.$axios = axios
Vue.prototype.$post = post
Vue.prototype.$get = get
複製代碼
2)組件中使用api
this.$post('/api/saveInfo', {
value: this.value,
requestName: 'name01'
}, '請求失敗啦~~~').then(res => {
// alert(res.data)
})
複製代碼
代碼:github地址連接服務器