/*
* @Description:
* @Author: NanKe
* @Date:
* @LastEditTime:
* @LastEditors: NanKe
* @Cnblogs: https://www.cnblogs.com/NanKe-Studying/
* @FilePath: \cloud-teach-aide\web\src\http.js
*/
import axios from 'axios'
import vueMain from './main'
const defaultConfig = {
baseURL: process.env.VUE_APP_BASEURL,
timeout: 30 * 1000, //超时时间,下面设置了超时重连机制
//如果设置超时时间太小,会报timeout of xxxms exceeded
//是因为请求+返回时间超过了设置的超时时间,比如网络不好或后台接口数据太过于庞大
retry: 2, //请求次数
retryDelay: 1000, //请求间隙
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}
const instance = axios.create(defaultConfig)
let loadingComponent
instance.interceptors.request.use(req => {
loadingComponent = vueMain.$buefy.loading.open();
// 1.比如req中的一些信息不符合服务器的要求,这里可以做一些修改
// 2.比如每次发送网络请求时,都希望在界面中显示一个请求的图标(然后再响应拦截中取消显示)
// 3.某些网络请求必须携带一些特殊的信息(如登录token),如果没有携带就可以拦截并作响应提示
// 4.某些请求要求用户必须登录, 判断用户是否有token, 如果没有token跳转到login页面
// 5.对请求的参数进行序列化(看服务器是否需要序列化) req.data = qs.stringify(req.data)
return req
}, err => {
// 请求未成功发出,如:没有网络...
return Promise.reject(err)
})
instance.interceptors.response.use(res => {
setTimeout(() => {
loadingComponent.close();
//下面是判断后端是调用了success还是fail响应给前端
let { code, message } = res.data
switch (code) {
case -1:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message
})
break;
case 0:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-black',
message
})
break;
case 200:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-success',
message
})
break;
}
}, 0.2 * 1000);
// 成功响应的拦截
return Promise.resolve(res.data)
}, err => {
if (err.response) {
// 失败响应的status需要在response中获得
switch (err.response.status) {
case 400:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message: "请求无效,请求未到达服务端"
})
break;
case 401:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message: "未授权的访问"
})
vueMain.$router.push('/')
break
case 403:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message: "禁止访问"
})
break;
case 404:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message: "页面不存在"
})
vueMain.$router.push('/')
break
case 405:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message: "不支持的方法"
})
break
default:
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message: "其他错误"
})
break
}
}
// 请求超时,重新请求
const { config, code, message } = err
if (code === 'ECONNABORTED' || message === 'Network Error') {
loadingComponent.close();
vueMain.$buefy.toast.open({
duration: 2000,
type: 'is-danger',
message: `请求超时,将在${defaultConfig.retryDelay / 1000}秒后重试`
})
}
// 如果config不存在或未设置重试选项,请拒绝
if (!config || !config.retry) return Promise.reject(err);
// 设置变量跟踪重试次数
config.__retryCount = config.__retryCount || 0;
// 检查是否已经达到最大重试总次数
if (config.__retryCount >= config.retry) {
// 抛出错误信息
return Promise.reject(err);
}
// 增加重试计数
config.__retryCount += 1;
// 创建新的异步请求
var backoff = new Promise(function (resolve) {
setTimeout(function () {
resolve();
}, config.retryDelay || 1);
});
// 返回axios信息,重新请求
return backoff.then(function () {
return axios(config);
});
// 注意这里应该return promise.reject(),因为如果直接return err则在调用此实例时,响应失败了也会进入then(res=>{})而不是reject或catch方法
// return Promise.reject(err)
})
export default instance