目录
1.Axios的默认配置
2.Axios创建Ajax实例对象发送请求
3.Axios拦截器
4.Axios取消请求
5.Axios文件结构说明
6.Axios创建过程
7.Axios对象创建过程模拟实现
8.Axios发送请求过程详解
9.模拟实现Axios发送请求
1.Axios的默认配置
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>axios基本使用</title>
<link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">基本使用</h2>
<button class="btn btn-primary"> 发送GET请求 </button>
<button class="btn btn-warning" > 发送POST请求 </button>
<button class="btn btn-success"> 发送 PUT 请求 </button>
<button class="btn btn-danger"> 发送 DELETE 请求 </button>
</div>
<script>
//获取按钮
const btns = document.querySelectorAll('button');
//设置默认配置,后续不用再设置
axios.defaults.method = 'GET';//设置默认的请求类型为 GET
axios.defaults.baseURL = 'http://localhost:3000';//设置基础 URL
axios.defaults.params = {id:100};//id等于100会加在url后面
axios.defaults.timeout = 3000;//
btns[0].onclick = function(){
axios({
//直接写路径和后面对应的url参数即可
url: '/posts'
}).then(response => {
console.log(response);
})
}
</script>
</body>
</html>
2.Axios创建Ajax实例对象发送请求
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>axios实例对象对象</title>
<link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">基本使用</h2>
<button class="btn btn-primary"> 发送GET请求 </button>
<button class="btn btn-warning" > 发送POST请求 </button>
<br>
</div>
<script>
//获取按钮
const btns = document.querySelectorAll('button');
//创建实例对象 /getJoke
//通过creat创建方法,接收的参数就是配置对象
const duanzi = axios.create({
baseURL: 'https://api.apiopen.top',
timeout: 2000
});
const onather = axios.create({
baseURL: 'https://b.com',
timeout: 2000
});
//这里 duanzi 与 axios 对象的功能几近是一样的
// duanzi({
// url: '/getJoke',
// }).then(response => {
// console.log(response);
// });
// 下面跟上面一样,只不过借助封装好的方法发送请求
duanzi.get('/getJoke').then(response => {
console.log(response.data)
})
</script>
</body>
</html>
3.Axios拦截器
拦截器(函数)分为两大类:1.请求拦截器 2.响应拦截器
请求拦截器:在发送请求之前,可以借助回调,来对请求的参数和内容做一些处理和检测,都没问题就可以发送请求,有问题就停止取消
响应拦截器:在数据返回我们处理结果之前对结果进行预处理,记录或者格式化处理,没有问题再交由我们自己自定义的回调进行处理
上面的例子:如果从第一步就抛出错误,第一个console.log会输出,但是返回的失败的promise,响应拦截器执行失败的,2的返回结果也是失败的promise,后续自己的回调函数就不能执行成功的了,只能执行失败的回调
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拦截器</title>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<script>
// Promise
// 设置请求拦截器 config 配置对象
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功 - 1号');
//修改 config 中的参数
config.params = {a:100};
return config;
}, function (error) {
console.log('请求拦截器 失败 - 1号');
return Promise.reject(error);
});
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功 - 2号');
//修改 config 中的参数
config.timeout = 2000;
return config;
}, function (error) {
console.log('请求拦截器 失败 - 2号');
return Promise.reject(error);
});
// 设置响应拦截器
axios.interceptors.response.use(function (response) {
console.log('响应拦截器 成功 1号');
return response.data;//只处理response其中的某一个部分(响应体)
// 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('自定义回调处理成功的结果');
console.log(response);//响应拦截器1号,只处理了响应体,回调函数打印出来也只有响应体
});
</script>
</body>
</html>
4.Axios取消请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>取消请求</title>
<link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">axios取消请求</h2>
<button class="btn btn-primary"> 发送请求 </button>
<button class="btn btn-warning" > 取消请求 </button>
</div>
<script>
//获取按钮
const btns = document.querySelectorAll('button');
//2.声明全局变量
let cancel = null;
//发送请求,为按钮绑定事件
btns[0].onclick = function(){
//发送请求之前检测上一次的请求是否已经完成
//cancel现在是null,执行完axios以后就变成c了
if(cancel !== null){
//不等于null就说明上一次的请求还在继续,取消上一次的请求
cancel();
}
//借助axios发送
axios({
method: 'GET',
url: 'http://localhost:3000/posts',
//1. 添加配置对象的属性,参数是函数
cancelToken: new axios.CancelToken(function(c){
//3. 将 c 的值赋值给 cancel
cancel = c;
})
}).then(response => {
console.log(response);
//请求完了以后将 cancel 的值初始化
cancel = null;
})
}
//绑定第二个事件取消请求
btns[1].onclick = function(){
cancel();
}
//delay -d延时 命令端启动的时候加-d 2000 发送请求延时两秒再返回结果
//这样就可以点击取消按钮了,要不然发送的太快取消按钮点不上
</script>
</body>
</html>
5.Axios文件结构说明
dist:存的是打包后的文件,最终输出的axios的整体文件,有两个一个是未压缩的axios.js,一个是压缩后的axios.min.js,在页面中使用
lib:整个的核心目录,所有的源代码都是放在这个文件中的
第一个子目录adapters:存放适配器
http:在node.js中向远端服务器发送http请求的(接口或爬虫),实现前端发送Ajax请求的功能
cancel:取消相关,通过new cancel创建一个实例对象 _CANCEL_识别我们这个对象是不是他的一个实例
CancelToken,本身是一个构造函数,实例化完了以后就可以对请求做一个取消
core: 核心功能文件
Axios.js放的是axios的构造函数,buildFullPath构建完整的url的函数文件,creatError创建error对象的,
dispatchrequest发送函数请求(适配器http和xhr发送请求前面的步骤:由dispatchrequest去调其中一个适配器发送请求)
enhanceError:更新错误对象的函数文件,InterceptorManager拦截器管理器的构造函数,
mergeConfig:合并配置的函数文件,settle:改变请求是成功状态还是失败状态的关键点,transformData对结果做转换
helpers:功能函数里面的
axios.js是Axios的入口文件
6.Axios创建过程
重要概括:先造了个axios函数出来,再在函数身上添加对应的方法和属性,又能当对象使
utils.extend可以将对象的方法进行复制,将目标对象身上的方法复制到我们的对象上去
defaults和interceptors默认配置对象和拦截器这个属性加进instance
instance:可以直接当函数使用/当对象使(身上多了方法)
7.Axios对象创建过程模拟实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> axios 的由来</title>
<!-- <script src="./node_modules/axios/dist/mine-axios.js"></script> -->
</head>
<body>
<!-- Axios身上有defaults/intercepters两个属性
我们创建Axios时,最后要记得把这两个属性添加上去 -->
<script>
// console.log(axios);
// axios();
// axios.get();
// axios.post();
//1.构造函数,接收参数是一个配置对象
function Axios(config){
//初始化
this.defaults = config;//为了创建 default 默认属性
//实际上是intercepters实例,里面是两个实例
this.intercepters = {
request: {},
response: {}
}
}
//原型添加相关的方法,
//get/post也能发送请求:因为core/axios.js中后面调了request方法
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'});
}
//2.声明函数 把instance整成axios
function createInstance(config){
//实例化一个对象context身上就有了intercepters
//由于原型上面有request,get,post,所以它也可以调用
//能调方法但是不能当函数使用
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函数对象中,遍历,把键拿过来结果就是request/get/post这三个属性
Object.keys(Axios.prototype).forEach(key => {//bind(context)绑到context上面
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({});
</script>
</body>
</html>
8.Axios发送请求过程详解
1.mergeConfig:将默认配置与用户调用时传入的配置进行合并,如果我们传进来的内容在默认配置里已经存在了,这个时候会覆盖,我们配置这个的优先级更高
2.在使用config时,若没有设置默认属性,最后会默认get
3.已经确认此时promise是成功的,执行第一个函数,chain是一个数组,执行里面的第一个方法,他的结果就是then方法的返回结果,决定下一次promise的值
9.模拟实现Axios发送请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请求发送过程</title>
<!-- <script src="./node_modules/axios/dist/mine-axios.js"></script> -->
</head>
<body>
<script>
// axios 发送请求
// axios创建过程是由Axios.prototype.request通过bind创建来的
//所以axios与request功能一模一样,两个都是函数,请求的源头是request
//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]);
//由于是成功的,所以执行第一个chains[0](就是2.dispatchRequest 函数)
//返回 promise 的结果
return result;//return返回axios这个函数执行的结果值
}
//成功时response就等于上面的result,成功的结果值,就是axios这个函数的执行结果(和request等效的)
//2. dispatchRequest 函数
//then方法一调返回结果一定是一个promise对象
function dispatchRequest(config){
//调用适配器发送请求
return xhrAdapter(config).then(response => {
//对响应的结果进行转换处理
//....
return response;
}, error => {
throw error;
});
}
//3. adapter 适配器
function xhrAdapter(config){//它执行的返回结果到上面由then方法去执行
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);
});
</script>
</body>
</html>