一、axios的使用
axios
是一个轻量的 HTTP
客户端基于 XMLHttpRequest
服务来执行 HTTP
请求,支持丰富的配置,支持 Promise
,支持浏览器端和 Node.js
端。
安装
// 项目中安装
npm install axios --S
// cdn 引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
使用
import axios from 'axios'
axios(config) // 直接传入配置
axios(url[, config]) // 传入url和配置
axios[method](url[, option]) // 直接调用请求方式方法,传入url和配置
axios[method](url[, data[, option]]) // 直接调用请求方式方法,传入data、url和配置
axios.request(option) // 调用 request 方法
const axiosInstance = axios.create(config)
// axiosInstance 也具有以上 axios 的能力
axios.all([axiosInstance1, axiosInstance2]).then(axios.spread(response1, response2))
请求拦截器
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);
});
取消请求
// 方式一
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('xxxx', {
cancelToken: source.token
})
// 取消请求 (请求原因是可选的)
source.cancel('主动取消请求');
// 方式二
const CancelToken = axios.CancelToken;
let cancel;
axios.get('xxxx', {
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
});
cancel('主动取消请求');
二、实现一个简易版axios
class Axios {
constructor() {
}
request(config) {
return new Promise(resolve => {
const {url = '', method = 'get', data = {}} = config;
// 发送ajax请求
const xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.onload = function() {
console.log(xhr.responseText)
resolve(xhr.responseText);
}
xhr.send(data);
})
}
}
导出axios
实例
function createAxiosRequest() {
let axios = new Axios();
let req = axios.request.bind(axios);
return req;
}
let axios = createAxiosRequest();
上述就已经能够实现axios({ })
这种方式的请求
下面是来实现下axios.method()
这种形式的请求
// 定义get,post...方法,挂在到Axios原型上
const methodsArr = ['get','post','delete'];
methodsArr.forEach(item => {
Axios.prototype[item] = function() {
if (['get', 'delete'].includes(item)) { // 2个参数(url[, config])
return this.request({
method: item,
url: arguments[0],
...arguments[1] || {}
})
} else { // 3个参数(url[,data[,config]])
return this.request({
method: item,
url: arguments[0],
data: arguments[1] || {},
...arguments[2] || {}
})
}
}
})
将Axios.prototype
上的方法搬运到request
上
function extend(a,b, context) {
for(let key in b) {
if (b.hasOwnProperty(key)) {
if (typeof b[key] === 'function') {
a[key] = b[key].bind(context);
} else {
a[key] = b[key]
}
}
}
}
// 修改导出的方法
function createAxiosRequest() {
let axios = new Axios();
let req = axios.request.bind(axios);
extend(req, Axios.prototype, axios)
return req;
}
实现axios.interceptors.response.use
和axios.interceptors.request.use,完整代码:
function extend(a,b, context) {
for(let key in b) {
if (b.hasOwnProperty(key)) {
if (typeof b[key] === 'function') {
a[key] = b[key].bind(context);
} else {
a[key] = b[key]
}
}
}
}
class Axios {
constructor() {
// 新增代码
this.interceptors = {
request: new InterceptorsManage,
response: new InterceptorsManage
}
}
request(config) {
// 拦截器和请求组装队列
let chain = [this.sendAjax.bind(this), undefined] // 成对出现的,失败回调暂时不处理
// 请求拦截
this.interceptors.request.handlers.forEach(interceptor => {
chain.unshift(interceptor.fullfield, interceptor.rejected)
})
// 响应拦截
this.interceptors.response.handlers.forEach(interceptor => {
chain.push(interceptor.fullfield, interceptor.rejected)
})
// 执行队列,每次执行一对,并给promise赋最新的值
let promise = Promise.resolve(config);
while(chain.length > 0) {
promise = promise.then(chain.shift(), chain.shift())
}
return promise;
}
sendAjax(config){
return new Promise(resolve => {
const {url = '', method = 'get', data = {}} = config;
const xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.onload = function() {
resolve(xhr.responseText);
};
xhr.send(data);
})
}
}
// 定义get,post...方法,挂在到Axios原型上
const methodsArr = ['get', 'delete', 'post'];
methodsArr.forEach(item => {
Axios.prototype[item] = function() {
// 处理单个方法
if (['get', 'delete'].includes(met)) { // 2个参数(url[, config])
return this.request({
method: item,
url: arguments[0],
...arguments[1] || {}
})
} else { // 3个参数(url[,data[,config]])
return this.request({
method: item,
url: arguments[0],
data: arguments[1] || {},
...arguments[2] || {}
})
}
}
})
class InterceptorsManage {
constructor() {
this.handlers = [];
}
use(fullfield, rejected) {
this.handlers.push({
fullfield,
rejected
})
}
}
function createAxiosRequest() {
let axios = new Axios();
let req = axios.request.bind(axios);
extend(req, Axios.prototype, axios)
// 把Axios上的方法和属性搬到request过去
// 现在request也有了interceptors对象,在发送请求的时候,会先获取request拦截器的handlers的方法来执行
extend(req, axios)
return req;
}