@TOC
Http 等介绍
Axios的特点
- 基本promise的异步ajax请求库
- 浏览器端/node端都可以使用
- 支持请求/响应拦截器
- 支持请求取消
- 请求/响应数据转换
- 批量发送多个请求
1.前后应用从浏览 器端向服务器发送HTTP请求(请求报文) 2.后台服务器接收到请求后,调度服务器应用处理请求,向浏览器端返回H响应(响应报文) 3.浏览器端接收到响应,解析显示响应体/调用监视回调
-
其它的HTTP请求和响应笔记----》请求头和响应头的其它笔记
-
GET请求没有请求体
-
POST不携带数据也没有请求体
-
配置对象是 属性名固定的
-
区别一般http请求与ajax请求
- ajax请求是一种特别的http请求
- 2.对服务 器端来说,没有任何区别,区别在浏览器端
- 3.浏览器端发请求:只有XHR或fetch发出的才是ajax请求,其它所有的都是,非ajax请求,
- 4.浏览器 端接收到响应 (1)一般请求:浏览器--般会直接显示响应体数据,也就是我们常说的刷新/跳转页面. (2)ajax请求:浏览器不会对界面进行任何更新操作,只是调用监视的回调函数并传入响应相关数据
-
请求行 method url GET /product_ detail?id=2 POST /login
-
多个请求头 Host: www.baidu.com Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3BOFA706; Content Type: application/x-www-form-urlencoded或者application/json // 两种数据类型传输
-
请求体 username=tom&pwd= 123 第一种数据类型 {"username": "tom", "pwd": 123} 第二种数据类型
-
响应状态行: status statusText
-
多个响应头 Content-Type: text/html;charset=utf-8 Set-Cookie: BD CK SAM= 1;path=/
-
响应体 html文本/json文本/js/css/图片...
- 响应状态字符串: 200 OK - 请求成功。一-般用于GET与POST请求 201 Created - 已创建.成功请求并创建了新的资源 401 Unauthorized - 未授权/请求要求用户的身份认证 404 Not Found - 服务器无法根据客户端的请求找到资源 500 Internal Server Error - 服务器内部错误,无法完成请求
- 不同类型的请求方式:
1.
GET:从服务器端读取数据 2.POST:向服务器端添加新数据 3.PUT:更新服务器端已经数据 4.DELETE:删除服务器端数据
服务成生成cookie数据返回给浏览器,再由请求头cookie拿到数据 POST 请求体参数格式:
- Content Type: application/x-www-form-urlencoded;charset=utf-8 用于键值对参数,参数的键值用=连接,参数之间用&连接 例如: name=%E5%B0%8F%E6%98%8E&age= 12
- Content-Type: application/json;charset=utf-8 用于json字符串参数 例如: {"name": "%E5%B0%8F%E6%98%8E", "age": 12}
- Content-Type: multipart/form-data 用于文本上传的请求
查询参数 params ? 和 query /
/ 得到的是直接选择的对象:http://localhost:3000/posts/1 或 ? 得到的是过滤后的数组 : http://localhost:3000/posts/?id=1
- API的分类
- REST API: restful (1) 发送请求进行CRUD哪个操作由请求方式来决定 (2) 同一个请求路径可以进行多个操作 (3 )请求方式会用到GET/POST/PUT/DELETE
- 非REST API: restless (1) 请求方式不决定请求的CRUD操作 (2) 一个请求路径只对应-一个操作. (3) 一般只有GET/POST
rest API 的接口创建 及介绍
API---> XMLHttpRequest 的MDN文档
-
XMLHttpRequest():创建XHR对象的构造函数 -
status: 响应状态码值,比如200, 404 -
statusText: 响应状态文本 -
readyState: 标识请求状态的只读属性(五个状态:数字) 0: 初始 1: open{)之后 2: send()之 后 3:请求中 4:请求完成 -
onreadystatechange:绑定readyState改变的监听 -
responseType:指定响应数据类型,如果是"json',得到响应后自动解析响应体数据 -
response响应体数据,类型取决于 response Type 的指定 -
timeout指定请求超时的时间 默认是 0 没限制 -
ontimeout绑定超时的监听 -
onerror:绑定请求网络错误的监听 -
open(): 初始化一个请求, 参数为: (method, urI[, async]) -
send(data): 发送请求 -
abort(): 中断请求 -
getResponseHeader(name)获取指定名称的响应头值 -
getAllResponseHeaders(): 获取所有响应头组成的字符串 -
setRequestHeader(name, value):设置请求头
创建 rest API 接口:rest API接口
- npm下载
npm install -g json-server - 创建 db.json文件 (database文件)
- 监听db.json文件
json-server --watch db.json配置完成后可以进行案例的操作:
axios的CRUD案例操作
<div>
<button onclick="testGet()">GET请求</button>
<button onclick="testPost()">POST请求</button>
<button onclick="testPut()">PUT请求</button>
<button onclick="testDelete()">DALETE请求</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
function testGet() {
// axios.get('http://localhost:3000/posts')
// axios.get('http://localhost:3000/posts/1') // params 返回对应 数据 1 的对像
axios.get('http://localhost:3000/posts/?id=1') // query 返回已筛选后的数组对象
.then(response => {
console.log('/posts get', response.data);
});
};
function testPost() {
axios.post('http://localhost:3000/posts', {"title": "json-server3", "author": "typicode3" })
.then(response => { // 添加 新的数据
console.log('/posts post', response.data);
});
};
function testPut() {
axios.put('http://localhost:3000/posts/3', {"title": "json-server...", "author": "typicode..." })
.then(response => { // 更新 3 的数据
console.log('/posts put', response.data);
});
};
function testDelete() {
axios.delete('http://localhost:3000/posts/3')
.then(response => { // 删除 3 的数据
console.log('/posts delete', response.data);
});
};
</script>
XML和Promise 封装简单的 Axios
<div>
<button onclick="testGet()">GET请求</button>
<button onclick="testPost()">POST请求</button>
<button onclick="testPut()">PUT请求</button>
<button onclick="testDelete()">DALETE请求</button>
</div>
<script>
// 1. GET请求:从服务器端获取数据
function testGet() {
axios({
// url:'http://localhost:3000/posts',
url:'http://localhost:3000/posts/1',
method: "GET",
}).then(response => {
console.log('成功了!!');
console.log(response);
},error => {
alert(error.message);
console.log(error);
});
};
// 2. POST请求:从服务器端添加/保存数据
function testPost() {
axios({
url:'http://localhost:3000/posts',
method: "POST",
parmas: {
id : "2",
name: "Liang"
},
data: {
"title": "json-server3",
"author": "typicode3"
}
}).then(response => {
console.log('成功了!!');
console.log(response);
},error => {
alert(error.message);
console.log(error);
});
};
// 3. PUT请求:从服务器端更新数据 传递 data 数据进行数据更新覆盖
function testPut() {
axios({
url:'http://localhost:3000/posts/1',
method: "put",
parmas: {
id : "xuex",
name: "Liang"
},
data: {
"title": "json-server+++",
"author": "typicode+++"
}
}).then(response => {
console.log('成功了!!');
console.log(response);
},error => {
alert(error.message);
console.log(error);
});
};
// 4. Delete请求:从服务器端删除数据 转递 query参数进行删除
function testDelete() {
axios({
url:'http://localhost:3000/posts/4',
method: "delete",
}).then(response => {
console.log('成功了!!');
console.log(response);
},error => {
alert(error.message);
console.log(error);
});
};
/*
1.函数的返回值为promise,成功的结果为response,异常的结果为error
2.能处理多种类型的请求: GET/POST/PUT/DELETE
3.函数的参数为一个配置对象
{
url : '', // 请求地址
method: ' ', //请求方式GET/POST/PUT/DELETE
params: {}, // GET/DELETE请求的query参数
data: {}, // POST或DELETE请求的请求体参数
}
4.响应json数据自动解析为js 的对象 、 数组
*/
function axios({url, method="GET", parmas={}, data={}}) {
// 处理method(转换成大写)
method = method.toUpperCase();
// 处理query参数(并接到url上) id=1&xxx=as
/*
{
id : 1,
}
*/
let queryString = '';
Object.keys(parmas).forEach(key => {
queryString += `${key}=${parmas[key]}&`;
});
if(queryString) {
// 去除最后的&
queryString = queryString.substring(0, queryString.length-1);
// 接到url
url += '?' + queryString;
}
// 返回一个Promise对象
return new Promise((resolve, reject) => {
// 1. 执行异步AJAX请求
let xhr = new XMLHttpRequest();
// 初始化,打开连接
xhr.open(method, url, true);
// 发送
if(method === "GET" || method === "DELETE") {
xhr.send();
}else if(method === "POST" || method === "PUT") {
xhr.setRequestHeader("Content-Type","application/json;charset=utf-8"); //
xhr.send(JSON.stringify(data)); // 发送 JSON 格式的请求体参数
}
// 监听变化
xhr.onreadystatechange = function() {
if(xhr.readyState !== 4) {
return;
}else {
// 2.1 如果请求成功,调用resolve()
if(xhr.status >= 200 && xhr.status < 300) {
// 准备结果数据对象response
const response = {
data : JSON.parse(xhr.response),
status: xhr.status,
statusText: xhr.statusText
}
resolve(response);
}else {
// 2.2 如果请求失败,调用reject()
reject(new Error('request error status is ' + status));
}
}
}
});
};
</script>
Axios 的常用语法
- axios(config):通用/最本质的发任意类型请求的方式
- axios(urI[, config):可以只指定url发get请求
- axios.request(config):等同于axios(config)
- axios. get(urI[, config]):发get请求
- axios.delete(url[, config]): 发delete请求
- axios.post(urI[, data, config]):发post请求
- axios.put(urI[, data, config]):发put请求
-
- axios. defaults.xxx:请求的默认全局配置
- axios.interceptors.request.use():添加请求拦截器
- axios.interceptors.response.use():添加响应拦截器
-
- axios.create([config]):创建一个 新的axios(它没有下面的功能)
- 根据指定配置创建一个新的axios,也就就每个新axios都有自己的配置
- 新axios只是没有取消请求和批量发请求的方法,其它所有语法都是一致的
- 为什么要设计这个语法? (1) 需求:项目中有部分接口需要的配置与另一-部分接口需要的配置不太一样,如何处理 (2)解决:创建2个新axios,每个都有自己特有的配置,分别应用到不同要求的接口请求中
-
- axios.Cancel():用于创建取消请求的错误对象
- axios.CancelToken():用于创建取消请求的token对象
- axios.isCancel():是否是-一个取消请求的错误
- axios all(promises):用于批量执行多个异步请求
- axios.spread(); 用来指定接收所有成功数据的回调函数方法
源码分析
- axios与Axios的关系? 1.从语法上来说: axios不是Axios的实例 2.从功能上来说: axios是Axios 的实例 3.axios 是Axios.prototype.request函数bind()返回的函数 4 axios 作为对象有Axios原型对象上的所有方法,有Axios对象上所有属性
- instance与axios的区别? 1.相同: (1)都是一个能发任意请求的函数: request(config) (2)都有发特定请求的各种方法: get()/post(/put()/delete() (3)都有默认配置和拦截器的属性: defaults/interceptors 2 不同 (1)默认匹配的值很可能不一样 (2) instance 没有axios 后面添加的一些方法:create() / CancelToken() / all()
base
<div>
<button onclick="testGet()">GET请求</button>
<button onclick="testPost()">POST请求</button>
<button onclick="testPut()">PUT请求</button>
<button onclick="testDelete()">DALETE请求</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
// axios.defaults.baseURL 指定默认配置
axios.defaults.baseURL = 'http://localhost:3000';
function testGet() {
// axios.get('http://localhost:3000/posts/?id=1') // 返回已筛选后的数组对象
axios({
url: '/posts',
params: {
id: 3
}
})
.then(response => {
console.log('/posts get', response.data);
});
};
function testPost() {
// axios.post('/posts', {"title": "json-server3", "author": "typicode3" })
axios({
url: '/posts',
method: 'post',
data: {"title": "json-server2", "author": "typicode2" }
})
.then(response => { // 添加 新的数据
console.log('/posts post', response.data);
});
};
function testPut() {
// axios.put('http://localhost:3000/posts/3', {"title": "json-server...", "author": "typicode..." })
axios({
url: '/posts/3',
method: 'put',
data: {"title": "json-server3", "author": "typicode3" }
})
.then(response => { // 更新 3 的数据
console.log('/posts put', response.data);
});
};
function testDelete() {
// axios.delete('http://localhost:3000/posts/3')
axios({
url: '/posts/3',
method: 'delete',
})
.then(response => { // 删除 3 的数据
console.log('/posts delete', response.data);
});
};
</script>
create
body>
<!-- axios.create(config)
* 根据指定配置创建一个新的axios,也就就每个新axios都有自己的配置
* 新axios只是没有取消请求和批量发请求的方法,其它所有语法都是一致的
* 为什么要设计这个语法?
(1) 需求:项目中有部分接口需要的配置与另一-部分接口需要的配置不太一样,如何处理
(2)解决:创建2个新axios,每个都有自己特有的配置,分别应用到不同要求的接口请求中
-->
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
axios.defaults.baseURL = 'http://localhost:3000';
// 使用 axios 发送请求
axios({
url: '/posts', // 请求 3000
});
/* axios({
url: '/xxx', // 请求 4000
}); */
const instance = axios.create({
baseURL: 'http://localhost:4000'
});
// 使用 instance
/* instance({
url: '/xxx', // 请求 4000
}); */
instance.get('/xxx');
</script>
拦截器
<script>
// 添加 请求拦截器 (回调函数) 后添加先执行
axios.interceptors.request.use(config => {
console.log('request interceptor1 onResolveed()');
return config;
}, error => {
console.log('request interceptor1 onRejected()');
return Promise.reject(error);
});
axios.interceptors.request.use(config => {
console.log('request interceptor 2 onResolveed()');
return config;
}, error => {
console.log('request interceptor 2 onRejected()');
return Promise.reject(error);
});
// 添加 响应拦截器
axios.interceptors.response.use(response => {
console.log('response interceptor 1 onResolveed()');
return response;
},error => {
console.log('response interceptor 1 onRejected()');
return Promise.reject(error);
});
axios.interceptors.response.use(response => {
console.log('response interceptor 2 onResolveed()');
return response;
},error => {
console.log('response interceptor 2 onRejected()');
return Promise.reject(error);
});
axios.get('http://localhost:3000/posts')
.then(response => {
console.log('data', response.data);
})
.catch(error => {
console.log('error', error.message);
});
/* 相同的请求 响应拦截器 不同的自己处理
axios.get('http://localhost/posts')
.then(response => {
console.log('data', response.data);
})
.catch(error => {
console.log('error', error.message);
}); */
</script>
取消请求 cancelToken
<body>
<button onclick="getProducts1()">获取商品列表1</button>
<button onclick="getProducts2()">获取商品列表2</button>
<button onclick="cancelReq()">取消请求</button>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
let cancel; // 用于保存取消请求的函数
function getProducts1() {
// 在准备发送请求前,取消未完成的请求函数
if(typeof cancel === 'function') {
cancel();
}
axios({
url : "http://localhost:4000/products1",
cancelToken: new axios.CancelToken(function executor(c) { // c 是用于取消当前请求的函数
// 保存取消函数,用于之后可能需要取消的当前请求
cancel = c;
})
}).then( response => {
cancel = null;
console.log('请求1成功了~~', response.data);
},
error => {
if(axios.isCancel(error)) {
// cancel = null;
console.log('请求1取消的错误~',error.message);
}else { // 请求出错了~
cancel = null;
console.log('请求1失败了~~',error.message);
}
});
};
function getProducts2() {
if(typeof cancel === 'function') {
cancel();
}
axios({
url : "http://localhost:4000/products2",
cancelToken: new axios.CancelToken(function executor(c) { // c 是用于取消当前请求的函数
// 保存取消函数,用于之后可能需要取消的当前请求
cancel = c;
})
}).then(response => {
cancel = null;
console.log('请求2成功了~~', response.data);
},error => {
if(axios.isCancel(error)) {
// cancel = null;
console.log('请求2取消的错误~',error.message);
}else { // 请求出错了~
cancel = null;
console.log('请求2失败了~~',error.message);
}
});
}
function cancelReq() {
// 执行强制取消请求的函数
if(typeof cancel === "function") {
cancel('强制取消请求~~~');
}else {
console.log('没有可取消的请求~');
}
}
</script>
</body>
拦截器 和 取消请求结合
<body>
<button onclick="getProducts1()">获取商品列表1</button>
<button onclick="getProducts2()">获取商品列表2</button>
<button onclick="cancelReq()">取消请求</button>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
// 添加请求拦截器
axios.interceptors.request.use(config => {
// 在准备发送请求前,取消未完成的请求函数
if(typeof cancel === 'function') {
cancel('取消请求~~');
}
// 添加 cancelToken的配置
confdig.cancelToken = new axios.CancelToken(function executor(c) { // c 是用于取消当前请求的函数
// 保存取消函数,用于之后可能需要取消的当前请求
cancel = c;
})
return config;
});
// 添加响应拦截器
axios.interceptors.response.use(
response => {
cancel = null;
return response;
},error => {
if(axios.isCancel(error)) { // 取消请求的错误
// cancel = null;
console.log('请求1取消的错误~',error.message);
// 中断 Promise 链
return new Promise(() => {});
}else { // 请求出错了~
// cancel = null;
// 将错误向下传递
// throw error;
return Promise.reject(error);
}
});
let cancel; // 用于保存取消请求的函数
function getProducts1() {
axios({
url : "http://localhost:4000/products1",
}).then( response => {
console.log('请求1成功了~~', response.data);
},
error => { // 只处理请求失败的情况,取消请求的错误的不同
console.log('请求1失败了~',error.message);
});
};
function getProducts2() {
axios({
url : "http://localhost:4000/products2",
}).then(response => {
console.log('请求2成功了~~', response.data);
},error => {
console.log('请求2失败了~~',error.message);
});
}
function cancelReq() {
// 执行强制取消请求的函数
if(typeof cancel === "function") {
cancel('强制取消请求~~~');
}else {
console.log('没有可取消的请求~');
}
}
</script>