axios
一、HTTP相关
1.1 HTTP请求交互的基本过程
-
前台应用从浏览器端向服务器发送HTTP请求(请求报文)
-
后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
-
浏览器端接收到响应, 解析显示响应体/保存数据并调用监视回调
1.2 HTTP请求报文
- 请求行
method url
GET /product_detail?id=2
POST /login
- 请求头
Host: www.baidu.com
Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3B0FA706;
Content-Type: application/x-www-form-urlencoded 或者 application/json
- 请求体
urlencoded格式: username=tom&pwd=123
json格式: {"username": "tom", "pwd": 123}
<script type="text/javascript">
//创建Ajax对象
var xhr=new XMLHttpRequest();
//2、告诉Ajax对象要向哪发送请求,以什么方式发送请求(请求方式,请求地址)
xhr.open('post','http://localhost:3000/json');
//通过请求头告诉服务器端客户端向服务器端传递的请求参数的格式是什么
xhr.setRequestHeader('Content-Type','application/json');
//JSON.stringify() 将json对象转换为json字符串
//3、发送请求
xhr.send(JSON.stringify({name:'lisi',age:22}));
//4、获取服务器端响应到客户端的数据
xhr.onload=function(){
console.log(xhr.responseText)//Hello Ajax
}
</script>
const express = require('express');
const bodyParser = require('body-parser')
const app = express();
app.use((request,response,next)=>{
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Headers','*');
next();
})
//extended:true,那么你可以解析嵌套对象,或者通常是任何类型
//extended:false,则只能解析字符串或数组
app.use(bodyParser.urlencoded()) //相当于{extended: true}
//接收json类型请求
app.use(bodyParser.json());
app.post('/server',(request,response)=>{
console.log(request.body);
response.send('server');
})
app.listen(80,()=>{
console.log('80端口正在运行中...');
})
1.3 HTTP响应报文
- 响应行
status statusText
200 OK
404 Not Found
- 响应头(多个)
Content-Type: text/html;charset=utf-8 text/json;charset=utf-8
Set-Cookie: BD_CK_SAM=1;path=/
- 响应体
html文本/json文本/js/css/图片...
1.4 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}
1.5 常见的响应状态码
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
401 Unauthorized 未授权/请求要求用户的身份认证
404 Not Found 服务器无法根据客户端的请求找到资源
500 Internal Server Error 服务器内部错误,无法完成请求
1.6 不同类型的请求及其作用
-
GET: 从服务器端读取数据
-
POST: 向服务器端添加新数据
-
PUT: 更新服务器端数据
-
PATCH: 更新服务器数据
-
DELETE: 删除服务器端数据
二、API的分类
API:Application program interface 应用程序接口,实际上封装好的一些功能的url地址
2.1 REST(restful)API
- 发送请求进行CURD哪个操作由请求方式来决定
- 同一个请求路径可以进行多个操作
- 请求方式会用到GET/POST/PUT/PATCH/DELETE
GET /zoos:列出所有动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息) 全部更新
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息) 局部更新
DELETE /zoos/ID:删除某个动物园
2.2 非REST(restless)API
- 请求方式不决定请求的CURD操作
- 一个请求路径只对应一个操作
- 一般只有GET/POST
GET /phone/1
POST /phone 新建手机信息
POST /phone/1/update 更新手机信息
POST /phone/1/delete 删除手机信息
三、使用json-server搭建REST API
3.1 json-server是什么
用来快速搭建模拟的REST API的工具包
3.2 json-server的使用
- 全局安装
npm i -g json-server
- 创建db.json
{
"posts": [
{
"id": 1,
"title": "json-server",
"author": "typicode"
},
{
"id": 2,
"title": "梅姐受伤啦!!!",
"author": "哔哩哔哩"
}
],
"phone": [
{
"id": 1,
"brand":"华为",
"color": "红色",
"price": 2000
}
],
"profile": {
"name": "typicode"
}
}
- 启动服务
json-server --watch(-w) db.json --port(-p) 端口号
列:json-server -w data.json -p 4000
四、什么是axios
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中,
是前端中最流行的ajax请求库,vue和react官方都推荐使用axios发送ajax请求
中文网:http://www.axios-js.com/zh-cn/docs/
bootcdn:https://www.bootcdn.cn/axios/
github:https://github.com/axios/axios
- 基于xhr + promise的异步ajax请求库
- 浏览器端/node端都可以使用
- 支持请求/响应拦截器
- 支持请求取消
- 请求/响应数据转换
- 批量发送多个请求
五、axios的基本使用
【注:目前使用js引入方式,后期项目中还是使用npm i axios包的安装方式】
- 发送get请求
语法:axios(config): 通用/最本质的发任意类型请求的方式
function sendGET(){
//该方法返回的结果为Promise对象。
axios({
//请求类型
method:'get',
//如果请求URL中需要携带参数,可以设置
params:{
id:1,
keyword:'女装'
},
//请求URL
url:"http://127.0.0.1/server",
//请求头
headers:{
a:1,
b:2
}
}).then(response=>{
console.log(response);
//结果是一个对象,其中包含config、data、headers、status、statusText、request
/*
* data:响应体
* headers:响应头
* status:响应状态码
* statusText:响应状态文本
* config:配置属性,包含的是本次请求中使用到的参数
* request: 发送ajax请求时所使用的XMLHttpRequest对象
*/
}).catch(error=>{
console.log(error)
})
)
- 发送post请求
function sendPOST(){
//该方法返回的结果为Promise对象。
axios({
//请求类型
method:'post',
//请求URL
url:"http://127.0.0.1/server",
//请求头
headers:{
a:1,
b:2
},
//请求体
data:"c=10&d=30"
//或者还可以写成对象的形式
//data:{c:10,d:30}
}).then(response=>{
console.log(response);
}).catch(error=>{
console.log(error)
})
}
- 发送put请求
function sendPut(){
//该方法返回的结果为Promise对象。
axios({
//请求类型
method:'put',
//请求URL
url:"http://127.0.0.1/server",
}).then(response=>{
console.log(response);
}).catch(error=>{
console.log(error)
})
}
需要在服务端中给添加响应的请求头
response.setHeader('Access-Control-Allow-Methods','*'); #允许任何请求类型来访问服务
- 发送delete请求
function sendDELETE(){
//该方法返回的结果为Promise对象。
axios({
//请求类型
method:'delete',
//请求URL
url:"http://127.0.0.1/server",
}).then(response=>{
console.log(response);
}).catch(error=>{
console.log(error)
})
}
5.1 axios使用独立方法发送请求
- axios.get(url[, config]): 发get请求
axios.get('http://127.0.0.1/server',{
params:{a:100,b:200},
headers:{c:300,d:400}
}).then(response=>{
console.log(response);
});
- axios.post(url[, data, config]): 发post请求
axios.post('http://127.0.0.1/server',{a:100,b:200},{
params:{x:10,y:20},
headers:{c:300,d:400}
}).then(response=>{
console.log(response);
});
5.2 axios的默认配置的使用
配置对象用来设定【请求的参数以及功能的设置】
/*
* method:请求类型
* url:请求的url
* params:请求的url参数
* headers:请求头
* data:请求体设置
* baseURL:设置url的公共部分
*/
//axios函数执行时,传入的对象就是[配置对象 ]
axios({
配置对象
})
axios.get('/server',{配置对象});
axios.post('/server',{},{配置对象})
//axios的默认属性配置,一旦配置了基础url,则后续请求都无需再写,请求时会自动添加
axios.defaults.baseURL = "http://127.0.0.1";
axios.get('/server');
axios.get('/json-server');
axios.get('/settings');
//设置默认超时时间
axios.defaults.timeout = 3000;
//设置默认请求类型
axios.defaults.method = 'GET';
5.3 axios创建实例对象发送请求
//创建实例对象
let duanzi = axios.create({
method:'GET',
baseURL:"https://v0.yiketianqi.com",
timeout:3000
});
//使用实例对象发送请求,使用方式与axios使用方式相同
duanzi({
url:'/api?unescape=1&version=v61&appid=82294778&appsecret=4PKVFula&city=北京'
}).then(response=>{
console.log(response);
});
5.4 axios拦截器使用
5.4.1 什么是拦截器
拦截器本质上其实就是一些函数,里面有两类拦截器,一个是请求拦截器;一个是响应拦截器。
请求拦截器的作用:对请求的内容以及参数做处理和检查。
响应拦截器的作用:对响应的内容进行预处理。
5.4.2 请求拦截器
axios.interceptors.request.use(config=>{
console.log('请求拦截器成功');
return config;
},error => {
console.error('请求拦截器失败');
return Promise.reject(error);
})
5.4.3 响应拦截器
axios.interceptors.response.use(response=>{
console.log('响应拦截器成功');
return config;
},error => {
console.error('响应拦截器失败');
return Promise.reject(error);
})
//发送请求
axios({
method:'get',
url:"http://127.0.0.1/server"
}).then(value=>{
console.log(value);
},reason=>{
console.error(reason);
})
拦截器可以设置多个,当请求拦截器有多个时则倒序执行;响应拦截器有多个时则正序执行;
axios.interceptors.request.use(config=>{
console.log('请求拦截器成功-1');
return config;
},error => {
console.error('请求拦截器失败-1');
return Promise.reject(error);
})
axios.interceptors.request.use(config=>{
console.log('请求拦截器成功-2');
return config;
},error => {
console.error('请求拦截器失败-2');
return Promise.reject(error);
})
axios.interceptors.response.use(response=>{
console.log('响应拦截器成功-1');
return config;
},error => {
console.error('响应拦截器失败-1');
return Promise.reject(error);
})
axios.interceptors.response.use(response=>{
console.log('响应拦截器成功-2');
return config;
},error => {
console.error('响应拦截器失败-2');
return Promise.reject(error);
})
5.5 axios取消请求
<body>
<button>发送请求</button>
<button>取消请求</button>
</body>
<script>
//获取按钮对象
let btns = document.querySelectorAll('button');
//声明变量
let cancel = null;
//发生点击事件
btns[0].onclick = function(){
//如果在发送之前想要取消则需要判断
/*
* 如果cancel已经为一个函数,则取消上一次请求
* if(cancel){
cancel();
}
*/
axios({
method:"GET"
url:"http://127.0.0.1/delay-server",
cancelToken:new axios.CancelToken(function(c){
cancel = c;
});
}).then(response=>{
console.log(response);
},error=>{
console.warn(error);
})
}
btns[1].onclick = function(){
//调用cancel函数
cancel();
}
</script>
服务端
app.all('/delay-server',(request,response)=>{
//延时
setTimeout(()=>{
response.send('Hello abc');
},3000);
})
六封装
//引入axios
import axios from 'axios'
// 引入nprogress,用来做进度条
import nprogress from 'nprogress'
import 'nprogress/nprogress.css'
// 创建axios实例
const request = axios.create({
baseURL:'/sph', //请求基本路径
timeout:5000, //超时时间
})
// 请求拦截器
request.interceptors.request.use((config)=>{
//进度条开始走
nprogress.start()
//在请求头中追加一个school(目前仅仅是为了测试,以后加的不是school,是token)
config.headers.school = 'atguigu'
//一定要记得,把配置项返回,否则请求信息全部丢失,无法正常请求
return config
})
// 响应拦截器
request.interceptors.response.use(
// 响应拦截器成功的回调
(response)=>{
// 进度条停止
nprogress.done()
/*
response是axios封装的响应对象,服务器返回的数据在data属性中。
将返回的真正数据交给使用者(此处.data一下,后期myAxios的使用者就不用再.data了)
*/
return response.data
},
// 响应拦截器失败的回调
(error)=>{
// 进度条停止
nprogress.done()
// 提示错误的原因
alert(error.message)
// 第一种处理:返回失败状态的Promise实例,失败的原因是error.message,使用者那里可以根据返回的异常,继续处理。
// return Promise.reject(error.message)
// 第二种处理:返回一个初始状态的Promise实例,中断掉Promise链,使用者那边就无需处理异常了。
return new Promise(()=>{})
}
)
export default myAxios