基础入门文档建议直接查看Axios中文文档,这样能少走很多弯路
Axios中文文档
封装请求
在请求或响应被 then 或 catch 处理前拦截它们
import axios from 'axios';
// axios 配置
var instance = axios.create({
headers:{
'Content-Type': 'application/json',
},
timeout: 30000,
baseURL: '', //接口请求地址
})
//拦截重复请求
let pending = []; //声明一个数组用于存储每个ajax请求的取消函数和ajax标识
let cancelToken = axios.CancelToken;
let removeRepeatUrl = (config) => {
let comValue = config.method == 'get' ? qs.stringify(config.params) : qs.stringify(config.data);
for(let p in pending){
if(pending[p].u === config.url + '&' + config.method + '&' + comValue) { //当前请求在数组中存在时执行函数体
pending[p].f(); //执行取消操作
pending.splice(p, 1); //把这条记录从数组中移除
}
}
}
let saveRepeatUrl = (config) =>{
let comValue = config.method == 'get' ? qs.stringify(config.params) : qs.stringify(config.data);
console.log(comValue)
config.cancelToken = new cancelToken((c)=>{
pending.push({ u: config.url + '&' + config.method + '&' + comValue, f: c }); // 自定义唯一标识
});
} }
}
// 添加请求拦截器
instance.interceptors.request.use(config => {
// 在发送请求之前做些什么,比如传token
removeRepeatUrl(config); //在一个ajax发送前执行一下取消操作
saveRepeatUrl(config); //保存请求地址
return config
}, error => {
// 对请求错误做些什么
console.log(error) // for debug
return Promise.reject(error);
})
// 添加响应拦截器
instance.interceptors.response.use(response => {
removeRepeatUrl(response.config); //执行取消操作,把已经完成的请求从pending中移除
// 对响应数据做点什么
const res = response.data;
//对错误代码做处理
return response;
}, error => {
// 对响应错误做点什么
console.log('err' + error)// for debug
return Promise.reject(error);
});
export default instance;
/**
* post 请求方法
* @param url
* @param data
* @returns {Promise}
*/
export function post(url, data = {}) {
return new Promise((resolve, reject) => {
instance.post(url, data).then(response => {
//对接口错误码做处理
resolve(response.data);
}, err => {
reject(err);
})
})
}
/**
* get 请求方法
* @param url
* @param data
* @returns {Promise}
*/
export function get(url, data = {}) {
return new Promise((resolve, reject) => {
instance.get(url, {
params: data
})
.then(response => {
resolve(response);
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装所有请求
* @param methed
* @param url
* @param data
* @param headers
* @returns {Promise}
*/
export function request(methed,url, data = {},headers) {
return new Promise((resolve, reject) => {
instance({
method: methed || 'post',
url:url,
params: methed === 'get' ? data :'',
data: methed !== 'get' ? data :'',
headers: headers || {'Content-Type':'application/json'},
})
.then(response => {
//对接口错误码做处理
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
调用方式
在 main.js文件中引用
import {post} from './utils/http'
Vue.prototype.$post = post;
最好将项目所有接口请求放在一个文件中,方便管理
新建文件api.js
import {request} from './axios.js'
//用户登录接口
export function userLogin(data){
return request('post','接口地址',data);
}
在其他页面引用
import {userLogin} from './api.js'
userLogin({}).then(res=>{
});
axios跨域
方法一
在config的index.js文件中的dev属性中添加一个属性proxyTable:
proxyTable{
'/api':{
target:"URL",
changeOrigin:true,
pathRewrite:{
'^/api':""
}
}
}
然后在axios里面访问 /api/xxx 就可以成功访问了这种方式只能本地测试环境运行,对正式环境无效(需要配置环境生效)
方法二:CORS(跨域资源共享)方案解决的跨域问题
跨域资源共享 CORS 详解
拦截重复请求
请看上面封装的请求代码(掩耳盗铃,只是拦截了服务端的响应,但是还是发了请求!!!!)
碰到的问题:
请求并没有真正取消,数据还是给发送到服务器了,所以取消请求不是真的取消请求?
正常情况下客户端发送的请求服务器是会接收到然后做处理的。而所谓的abort,是指不接收请求的响应数据而不是拦截。因此某种意义上对于get类的请求
来说是有效的,但是对post类请求不行。
http请求是基于tcp的,abort取消的是http层面的请求,如果abort的时候,请求已经到达tcp层面了最终是还会到达服务器端的,只是不会再接收服务端的
响应了