axios
Note
基本使用#
const btns = document.querySelectorAll('button')
btns[1].addEventListener('click', function() {
axios({
method: 'POST',
url: 'http://127.0.0.1:8888/json-server',
data: {
title: 'wang',
age: 18
}
}).then(response => {
console.log(response)
})
})
axios.post('http://localhost:8888/json-server', {
title: 'wang'
}).then(response => {
console.log(response.data)
})
配置对象#
请求配置#
axios.request({
method: 'POST',
url: 'http://127.0.0.1:8888/json-server',
// `params` 是即将与请求一起发送的 URL 参数
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象
params: {
title: 'wang'
},
data: {
age: 18
},
// `headers` 是即将被发送的自定义请求头
headers: { 'X-Requested-With': 'XMLHttpRequest' },
// `transformRequest` 允许在向服务器发送前,修改请求数据
// 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
transformRequest: [function(data, headers) {
console.log('transformRequest', data)
console.log('transformRequest', headers)
}],
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function(data) {
console.log('transformResponse', data)
return data
}],
// `paramsSerializer` 是一个负责 `params` 序列化的函数
/* paramsSerializer: function(params) {
}, */
// `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求花费了超过 `timeout` 的时间,请求将被中断
timeout: 1000,
// `withCredentials` 表示跨域请求时是否需要使用凭证
withCredentials: false, // default
// 具体配置可以查看http://www.axios-js.com/zh-cn/docs/
}).then(response => {
console.log(response)
})
响应结构#
{
// `data` 由服务器提供的响应
data: {},
// `status` 来自服务器响应的 HTTP 状态码
status: 200,
// `statusText` 来自服务器响应的 HTTP 状态信息
statusText: 'OK',
// `headers` 服务器响应的头
headers: {},
// `config` 是为请求提供的配置信息
config: {},
// 'request'
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance the browser
request: {}
}
全局的默认值#
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.timeout = 3000
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
创建实例对象#
//创建实例对象
const axiosTest = axios.create({
baseURL: 'https://api.apiopen.top/api',
timeout: 2000
})
// 功能与axios对象的功能基本是一样的
axiosTest({
url: '/sentences'
}).then(response => {
console.log(response.data)
})
axios拦截器#
// 请求拦截器
// config 配置对象
axios.interceptors.request.use(function(config) {
console.log('请求拦截器 成功 - 1')
config.params = { a: 100 } // 修改配置
config.timeout = 2000
return config
}, function(error) {
console.log('请求拦截器 失败 - 1')
return Promise.reject(error)
})
// 响应拦截器
axios.interceptors.response.use(function(response) {
console.log('响应拦截器 成功 - 1')
return response.data // 直接返回数据
}, function(error) {
console.log('响应拦截器 失败 - 1')
return Promise.reject(error)
})
axios({
method: 'GET',
url: '/sentences',
baseURL: 'https://api.apiopen.top/api'
}).then(response => {
console.log(response)
})
取消请求#
let cancel = null
btns[0].addEventListener('click', function() {
// 检测上一次的请求是否完成
cancel !== null ? cancel() : undefined
axios({
method: 'GET',
url: '/json-server',
baseURL: 'http://localhost:8888',
// 添加属性
cancelToken: new axios.CancelToken(function executor (c) {
// 将c赋值给cancel
cancel = c
})
}).then(response => {
// cancel初始化
cancel = null
console.log(response.data.result)
})
})
源码#
axios对象创建过程#
//构造函数
function Axios (config) {
//初始化
this.defaults = config;//为了创建 default 默认属性
this.intercepters = {
request: {},
response: {}
}
}
//原型添加相关的方法
Axios.prototype.request = function(config) {
console.log('发送 AJAX 请求 请求的类型为 ' + config.method);
}
Axios.prototype.get = function(config) {
return this.request({ method: 'GET' });
}
Axios.prototype.post = function(config) {
return this.request({ method: 'POST' });
}
//声明函数
function createInstance (config) {
//实例化一个对象
let context = new Axios(config);// context.get() context.post() 但是不能当做函数使用 context() X
//创建请求函数
let instance = Axios.prototype.request.bind(context);// instance 是一个函数 并且可以 instance({}) 此时 instance 不能 instance.get X
//将 Axios.prototype 对象中的方法添加到instance函数对象中
Object.keys(Axios.prototype).forEach(key => {
instance[key] = Axios.prototype[key].bind(context);// this.default this.interceptors
});
//为 instance 函数对象添加属性 default 与 interceptors
Object.keys(context).forEach(key => {
instance[key] = context[key];
});
return instance;
}
let axios = createInstance();
//发送请求
// axios({method:'POST'});
axios.get({});
axios.post({});
模拟实现axios发送请求#
// axios 发送请求 axios Axios.prototype.request bind
//1. 声明构造函数
function Axios(config){
this.config = config;
}
Axios.prototype.request = function(config){
//发送请求
//创建一个 promise 对象
let promise = Promise.resolve(config);
//声明一个数组
let chains = [dispatchRequest, undefined];// undefined 占位
//调用 then 方法指定回调
let result = promise.then(chains[0], chains[1]);
//返回 promise 的结果
return result;
}
//2. dispatchRequest 函数
function dispatchRequest(config){
//调用适配器发送请求
return xhrAdapter(config).then(response => {
//响应的结果进行转换处理
//....
return response;
}, error => {
throw error;
});
}
//3. adapter 适配器
function xhrAdapter(config){
console.log('xhrAdapter 函数执行');
return new Promise((resolve, reject) => {
//发送 AJAX 请求
let xhr = new XMLHttpRequest();
//初始化
xhr.open(config.method, config.url);
//发送
xhr.send();
//绑定事件
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//判断成功的条件
if(xhr.status >= 200 && xhr.status < 300){
//成功的状态
resolve({
//配置对象
config: config,
//响应体
data: xhr.response,
//响应头
headers: xhr.getAllResponseHeaders(), //字符串 parseHeaders
// xhr 请求对象
request: xhr,
//响应状态码
status: xhr.status,
//响应状态字符串
statusText: xhr.statusText
});
}else{
//失败的状态
reject(new Error('请求失败 失败的状态码为' + xhr.status));
}
}
}
});
}
//4. 创建 axios 函数
let axios = Axios.prototype.request.bind(null);
axios({
method:'GET',
url:'http://localhost:3000/posts'
}).then(response => {
console.log(response);
});
axios拦截器原理#
//构造函数
function Axios (config) {
this.config = config;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager(),
}
}
//发送请求 难点与重点
Axios.prototype.request = function(config) {
//创建一个 promise 对象
let promise = Promise.resolve(config);
//创建一个数组
const chains = [dispatchRequest, undefined];
//处理拦截器
//请求拦截器 将请求拦截器的回调 压入到 chains 的前面 request.handles = []
this.interceptors.request.handlers.forEach(item => {
chains.unshift(item.fulfilled, item.rejected);
});
//响应拦截器
this.interceptors.response.handlers.forEach(item => {
chains.push(item.fulfilled, item.rejected);
});
// console.log(chains);
//遍历
while (chains.length > 0) {
promise = promise.then(chains.shift(), chains.shift());
}
return promise;
}
//发送请求
function dispatchRequest (config) {
//返回一个promise 队形
return new Promise((resolve, reject) => {
resolve({
status: 200,
statusText: 'OK'
});
});
}
//创建实例
let context = new Axios({});
//创建axios函数
let axios = Axios.prototype.request.bind(context);
//将 context 属性 config interceptors 添加至 axios 函数对象身上
Object.keys(context).forEach(key => {
axios[key] = context[key];
});
//拦截器管理器构造函数
function InterceptorManager () {
this.handlers = [];
}
InterceptorManager.prototype.use = function(fulfilled, rejected) {
this.handlers.push({
fulfilled,
rejected
})
}
//以下为功能测试代码
// 设置请求拦截器 config 配置对象
axios.interceptors.request.use(function one (config) {
console.log('请求拦截器 成功 - 1号');
return config;
}, function one (error) {
console.log('请求拦截器 失败 - 1号');
return Promise.reject(error);
});
axios.interceptors.request.use(function two (config) {
console.log('请求拦截器 成功 - 2号');
return config;
}, function two (error) {
console.log('请求拦截器 失败 - 2号');
return Promise.reject(error);
});
// 设置响应拦截器
axios.interceptors.response.use(function(response) {
console.log('响应拦截器 成功 1号');
return response;
}, function(error) {
console.log('响应拦截器 失败 1号')
return Promise.reject(error);
});
axios.interceptors.response.use(function(response) {
console.log('响应拦截器 成功 2号')
return response;
}, function(error) {
console.log('响应拦截器 失败 2号')
return Promise.reject(error);
});
//发送请求
axios({
method: 'GET',
url: 'http://localhost:3000/posts'
}).then(response => {
console.log(response);
});
axios 取消请求工作#
//构造函数
function Axios (config) {
this.config = config;
}
//原型 request 方法
Axios.prototype.request = function(config) {
return dispatchRequest(config);
}
//dispatchRequest 函数
function dispatchRequest (config) {
return xhrAdapter(config);
}
//xhrAdapter
function xhrAdapter (config) {
//发送 AJAX 请求
return new Promise((resolve, reject) => {
//实例化对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open(config.method, config.url);
//发送
xhr.send();
//处理结果
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
//判断结果
if (xhr.status >= 200 && xhr.status < 300) {
//设置为成功的状态
resolve({
status: xhr.status,
statusText: xhr.statusText
});
} else {
reject(new Error('请求失败'));
}
}
}
//关于取消请求的处理
if (config.cancelToken) {
//对 cancelToken 对象身上的 promise 对象指定成功的回调
config.cancelToken.promise.then(value => {
xhr.abort();
//将整体结果设置为失败
reject(new Error('请求已经被取消'))
});
}
})
}
//创建 axios 函数
const context = new Axios({});
const axios = Axios.prototype.request.bind(context);
//CancelToken 构造函数
function CancelToken (executor) {
//声明一个变量
var resolvePromise;
//为实例对象添加属性
this.promise = new Promise((resolve) => {
//将 resolve 赋值给 resolvePromise
resolvePromise = resolve
});
//调用 executor 函数
executor(function() {
//执行 resolvePromise 函数
resolvePromise();
});
}
//获取按钮 以上为模拟实现的代码
const btns = document.querySelectorAll('button');
//2.声明全局变量
let cancel = null;
//发送请求
btns[0].onclick = function() {
//检测上一次的请求是否已经完成
if (cancel !== null) {
//取消上一次的请求
cancel();
}
//创建 cancelToken 的值
let cancelToken = new CancelToken(function(c) {
cancel = c;
});
axios({
method: 'GET',
url: 'http://localhost:3000/posts',
//1. 添加配置对象的属性
cancelToken: cancelToken
}).then(response => {
console.log(response);
//将 cancel 的值初始化
cancel = null;
})
}
//绑定第二个事件取消请求
btns[1].onclick = function() {
cancel();
}