Axios入门

HTTP相关

MDN文档

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview

HTTP请求报文

请求行

格式: method url

例如: GET/product_detail?id=2 或 POST / login

请求头(一般有多个请求头)

Host: www.baidu.com

Cookie: BAIDUID=AD3B0FA706E;BIDUPSID=AD3B0FA706;

Content-Type: applicartion/x-www-from-urlencoded 或者 application/json

请求体 (get没有)

username=tom&pwd=123

{“username”:”tom”,”pwd”:123}

HTTP响应报文

响应行

格式: status status Text

例如: 200 OK 或 404 Not Found

响应头(一般有多个)

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 Serve Error 服务器内部错误,无法完成请求

请求方式与请求参数

请求方式

GET(索取):从服务端读取数据 —– 查(R –Retrieve)

POST(交差):向服务端添加新数据 —– 增(C –Create)

PUT:更新服务端已经存在的数据 —— 改(U –Update)

DELETE:删除服务器端数据 —— 删(D –Delete)

请求参数

query参数(查询字符串参数)
  • 参数包含在请求地址中,格式为:/xxxx?name=tom&age=18
  • 敏感数据不要用query参数,因为参数是地址的一部分,比较危险
  • 备注:query参数又称为查询字符串参数,编码方式为urlencoded
params参数
请求体参数(body)
  • 参数包含在请求体中,可通过浏览器开发工具查看

  • 常用的两种格式:

    格式一:urlencoded格式

    例如:name=tom&age=18

    对于请求头:Content-Type:application/x-www-from-urlencoded

​ 格式二:json格式

​ 例如:{“name”:”tom”,”:age”:12}

​ 对应请求头:Content-Type:application/json

特别注意:

  • GET请求不能携带请求体参数,因为GET请求没有请求体

  • 理论上一次请求可以随意使用上述3种类型参数中的任何一种,甚至一次请求的3个参数可以用3种形式携带,但一般不这样做

  • 一般来说我们有一些”约定俗成”的规矩:

    (1):例如 from 表单发送 post 请求时,自动使用请求体参数,用urlencoded编码

​ (2):例如 jQuery 发送ajax-post请求时,自动使用请求体参数,用urlencoded编码

  • 开发中请求到底发给谁?用什么方式? 携带什么参数? —要参考项目的API接口文档

API相关

API的分类

REST API(restful 风格的 API)

  • 发送请求进行 CRUD(增查改删) 哪个操作由请求方式来决定

  • 同一个请求路径可以进行多个操作

  • 请求方式会用到 GET / POST / PUT / DELETE

    const express = require('express')
    // 实例一个app服务对象
    const app = express()
    app.get('/person',(req,res)=>{
        res.send('一些人的数据给你了')
    })
    app.post('/person',(req,res)=>{
        res.send('你成功的添加了一个人')
    })
    app.put('/person',(req,res)=>{
        res.send('你成功的修改了一个人')
    })
    app.post('/person',(req,res)=>{
        res.send('你成功的删除了一个人')
    })
    app.listen(8090,(error)=>{
        if(!error) console.log('服务器开启成功了');
    })

非 REST API (restless 风格的 API)

  • 请求方式不决定请求的 CRUD 操作
  • 一个请求路径只对应一个操作
  • 一般只有 GET / POST
// 早些年都这么写,两个请求有4个路径 --不能清晰表达要干嘛
const express = require('express')
// 实例一个app服务对象
const app = express()
app.get('/get_person',(req,res)=>{
    res.send('一些人的数据给你了')
})
app.post('/add_person',(req,res)=>{
    res.send('你成功的添加了一个人')
})
app.post('/update_person',(req,res)=>{
    res.send('你成功的修改了一个人')
})
// 请求方式不决定请求的 CRUD 操作
app.post('/delete_person',(req,res)=>{
    res.send('你成功的删除了一个人')
})
app.listen(8090,(error)=>{
    if(!error) console.log('服务器开启成功了');
})

使用 json-server 搭建 REST API

json-server是什么?

  • 用来快速搭建REST API 风格的工具包

使用 json-server

  • 在线文档:http:github.com/typicode/json-serrver

  • 下载:npm install -g json-server
    
    
    - 目标根目录下创建数据库 **json** 文件:**db.json**
    
    { "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } }
    
    - 启动服务器执行命令:json-server --watch db.json   (watch可以省略 db可以改为任意喜欢的名字)
    
      
    
    #### 使用浏览器访问测试
    
    http://localhost:3000/posts
    
    http://localhost:3000/comments
    
    http://localhost:3000/profile
    
    
    
    #### 使用postmon接口测试
    
    **json-server服务器注意:**
    
    - postmon测试中发送PUT请求,能在请求体携带id参数(或者使用params携带id),不能用query参数携带id
    
    - postmon测试中发送DELETE请求,只能使用params携带参数(json-server模拟的服务器,id都得通过params携带,其他有请求体就用请求体,没有就正常使用params或者query)
    
      
    
    #### 一般 http 请求与 ajax 请求
    
    - ajax请求是一种特别http请求
    
    -  对服务器端来说,没有任何区别,区别在浏览器端
    
    - 浏览器端发请求:只有XHR或fetch发出得才是ajax请求。其他所有得都是非ajax请求
    
    - 浏览器端接收到响应
    
      ​	(1) 一般请求:浏览器一般会直接显示响应体数据,也就是我们常说得自动刷新/跳转页面
    
      ​	(2)ajax 请求:浏览器不会对界面进行任何更新操作,只是调用监视得回调函数传入响应相关数据
    
      
    
    ## axios的理解和使用
    
    ### axios是什么
    
    1.前端最流行的ajax请求库
    
    2.react/vue官方都推荐使用axios发ajax请求
    
    3.文档:https://github.com/axios/axios
    
    ### axios特点
    
    1.基于Promise的异步ajax请求库
    
    2.浏览器端/node端都可以使用
    
    3.支持请求/响应拦截器
    
    4.支持请求取消
    
    5.请求/响应数据转换
    
    6.批量发送多个请求
    
    ### 使用axios发送ajax请求
    
    - 终端打开准备好的server文件夹里使用api-doc工具制作的api文档
    - 新建 '1_axios的基本使用.html' 文件,同时新建一个js文件夹存放axios.mini.js文件,引入到html里
    
    **准备按钮、文本框**
    
    ```html
    <button id="btn1">点我获取所有人</button><br><br>
    <button id="btn2">点我获取某个人</button>
    <input id="person_id" type="text" placeholder="请输入一个人的id"><br><br>
    <button id="btn3">点我添加一个人</button>
    <input id="person_name" type="name" placeholder="请输入一个人的名字">
    <input id="person_age" type="age" placeholder="请输入一个人的年龄"><br><br>
    <button id="btn4">点我更新一个人</button>
    <input id="person_update_id" type="text" placeholder="请输入一个人的id">
    <input id="person_update_name" type="text" placeholder="请输入名字">
    <input id="person_update_age" type="text" placeholder="请输入年龄"><br /><br />
    <button id="btn5">点我删除一个人</button>
    <input id="person_delete_id" type="text" placeholder="请输入删除的id">

获取按钮、文本框

const btn1 = document.getElementById('btn1')
const btn2 = document.getElementById('btn2')
const btn3 = document.getElementById('btn3')
const personId = document.getElementById('person_id')
const personName = document.getElementById('person_name')
const personAge = document.getElementById('person_age')
const btn4 = document.getElementById('btn4')
const btn5 = document.getElementById('btn5')
const personUpdateId = document.getElementById('person_update_id')
const personUpdateName = document.getElementById('person_update_name')
const personUpdateAge = document.getElementById('person_update_age')
const personDeleteId = document.getElementById('person_delete_id')

获取所有人的信息 —发送GET请求 —不携带参数

// 获取所有人的信息 ---发送GET请求 ---不携带参数 
btn1.onclick = () => {
    // 完整版
    axios({
        url: 'http://localhost:5000/persons', //请求地址
        method: 'GET', //请求方式
    }).then(
        (response) => { console.log('请求成功了',response.data)},
        (error) => { console.log('请求失败了',error) }
    )
    
    // 精简版
    axios.get('http://localhost:5000/persons').then(
         response => {console.log('请求成功了',response.data)},
         error => {console.log('请求失败了',error)}
    )
}

// 如果只想获取到成功的值 可以使用await 方法更简单
btn1.onclick = async() => {
    const result = await axios.get('http://localhost:5000/persons')
    console.log(result.data)
}

使用axios发送其他请求

发送GET请求

获取某个人—发送GET请求—携带query参数

//获取某个人---发送GET请求---携带query参数
btn2.onclick = () => {
    // 完整版
    axios({
        url: 'http://localhost:5000/person',
        method: 'GET',
        params: { id: personId.value }//此处写的是params,但携带的是query参数
    }).then(
        response => {
            console.log('请求成功了', response.data);
        },
        error => { '请求失败了', error }
    )
    
    // 精简版
    axios.get('http://localhost:5000/person', { params: { id: personId.value } }).then(
        response => { console.log('成功了', response.data); },
        error => { console.log('失败了', error); }
    )
}

发送POST请求

添加一个人—发送POST请求—携带json编码参数 或 urlencoded编码

btn3.onclick = ()=> {
axios({
     // 完整版
     url:'http://localhost:5000/person',
     method:'POST',
     data:{name:personName.value,age:personAge.value} //携带请求体参数(json编码)
}).then(
    response => {
         console.log('请求成功了', response.data);
    },
    error => { 
          console.log('请求失败了', error);
     }
    )
    // 精简版
axios.post('http://localhost:5000/person',`name=${personName.value}&age=${personAge.value}`).then(
	// axios.post('http://localhost:5000/person',{name:personName.value,age:personAge.value}).then(
     		response => {console.log('请求成功了',response.data)},
      		error => {console.log('请求失败了',error)}
      )    
}

发送PUT请求

更新一个人—发送PUT请求—携带json编码参数 或 urlencoded编码

btn4.onclick = () => {
    // 完整版
    axios({
        url: 'http://localhost:5000/person',
        method: 'PUT',
        data: {
            id:personUpdateId.value, 
            name:personUpdateName.value, 
            age:personUpdateAge.value
        },
    }).then(
            response => {
                console.log('请求成功了', response.data);
            },
            error => { 
                console.log('请求失败了', error);
             }
    )
    
    //精简版
    axios.put('http://localhost:5000/person',{
        id:personUpdateId.value,
        name:personUpdateName.value,
        age:personUpdateAge.value
    }).then(
        response => { console.log('请求成功了', response.data) },
        error => { console.log('请求失败了', error) }
    )
}

发送DELETE请求

删除一个人—发送DELETE请求—携带params参数

btn5.onclick = ()=> {
       axios({
           url:`http://localhost:5000/person/${personDeleteId.value}`,
           method:'DELETE',
       }).then(
           (response)=>{console.log('请求成功了',response.data);},
           (error)=>{console.log('请求失败了',error);}
       )
}

结论

  • axios调用的返回值是Promise实例

  • 成功的值叫response,失败的值叫error

  • axios成功的值是一个axios封装的response对象,服务器返回的真正数据在response.data中

  • 携带query参数时,编写的配置项叫做params

  • 携带params参数时,就需要自己手动拼在url中

axios常用配置项

新建‘2_axios常用配置项.html’文件,引入‘axios.min.js’

<button id="btn">点我获取所有人</button><br/><br/>
<script type="text/javascript" >
	const btn = document.getElementById('btn')
	//给axios配置默认属性
	axios.defaults.timeout = 2000
	axios.defaults.headers = {school:'atguigu'}
	axios.defaults.baseURL = 'http://localhost:5000'
	btn.onclick = ()=>{
			axios({
				url:'/persons', //请求地址
				method:'GET',//请求方式
				//params:{delay:3000},//配置query参数
				//data:{c:3,d:3},//配置请求体参数(json编码)
				//data:'e=5&f=6',//配置请求体参数(urlencoded编码)
				//timeout:2000,//配置超时时间
				//headers:{school:'atguigu'} //配置请求头
				//responseType:'json'//配置响应数据的格式(默认值)
			}).then(
				response => {console.log('成功了',response.data);},
				error => {console.log('失败了',error);}
			)
		}
</script>

axios常用语法

新建’3_axios.create方法.html‘,引入‘axios.min.js’

axios.create(config)

  • 根据指定配置创建一个新的axios, 也就是每个新axios都有自己的配置

  • 新axios只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的

  • 为什么要设计这个语法?

    需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样

<button id="btn3">点我获取笑话信息</button><br/><br/>
<script type="text/javascript" >
	const btn3 = document.getElementById('btn3')

	// 创建一个新的axios 
	const axios2 = axios.create({
			timeout:3000,
			//headers:{name:'tom'},
			baseURL:'https://api.apiopen.top/api'
	})
    //给原axios配置默认属性
	axios.defaults.timeout = 2000
	axios.defaults.headers = {school:'atguigu'}
	axios.defaults.baseURL = 'http://localhost:5000'

	btn3.onclick = ()=>{
		axios2({
			url:'/getImages',
			method:'GET'
		}).then(
			response => {console.log('成功了',response.data);},
			error => {console.log('失败了',error);}
		)
	}
</script>

拦截器函数/ajax请求/请求的回调函数

axios请求拦截器
1.是什么?
在真正发请求前执行的一个回调函数
2.作用:
对所有的请求做统一的处理:追加请求头、追加参数、界面loading提示等等

新建’4_axios中的拦截器.html‘,引入‘axios.min.js’

<button id="btn">点我获取所有人</button><br/><br/>
<script type="text/javascript" >
const btn = document.getElementById('btn')
//请求拦截器
axios.interceptors.request.use((config)=>{
		console.log('请求拦截器1执行了');
		// 如果时间戳是偶数 就加上请求头
		if(Date.now() % 2 === 0){
			config.headers.token = 'atguigu'
		}
			console.log(config);
			return config
})
btn.onclick = ()=>{
		axios.get('http://localhost:5000/persons').then(
			response => {console.log('成功了',response.data)},
			error => {console.log('失败了',error);}
		)
}
</script>

axios响应拦截器
1.是什么?
得到响应之后执行的一组回调函数
2.作用:
若请求成功,对成功的数据进行处理
若请求失败,对失败进行统一的操作

<button id="btn">点我获取所有人</button><br/><br/>
<script type="text/javascript" >
const btn = document.getElementById('btn')
//响应拦截器
axios.interceptors.response.use(
	response => {
		console.log('响应拦截器成功的回调执行了',response);
		if(Date.now() % 2 === 0) {
			return response.data
		} else {
			return '时间戳不是偶数,不能给你数据'
		}
	},
	error => {
		console.log('响应拦截器失败的回调执行了');
		alert(error);
		return new Promise(()=>{})
	}
)

btn.onclick = async ()=>{
	const result = await axios.get('http://localhost:5000/persons2')
	console.log(result);
}
</script>

取消请求

<button id="btn">点我获取测试数据</button><br/><br/>
<button id="btn2">取消请求</button><br/><br/>
    
<script type="text/javascript" >
	const btn = document.getElementById('btn')
	const btn2 = document.getElementById('btn2')
	const {CancelToken} = axios //CancelToken能为一次请求“打标识”
	let cancel
	btn.onclick = async()=>{
		axios({
			url:'http://localhost:5000/test1?delay=3000',
			cancelToken:new CancelToken((c)=>{ //c是一个函数,调用c就可以关闭本次请求
				cancel = c
			})
		}).then(
			response => {console.log('成功了',response.data);},
			error => {console.log('失败了',error);}
		)
	}
	btn2.onclick = ()=>{
		cancel()
	}
</script>

取消请求和拦截器配合使用

<button id="btn">点我获取测试数据</button><br/><br/>
<button id="btn2">取消请求</button><br/><br/>
<script type="text/javascript" >
	const btn = document.getElementById('btn')
	const btn2 = document.getElementById('btn2')
	// axios里面有个isCancel方法专门用于判断错误,还是用户取消请求导致的不合理。使用{}取出isCancel
	const {CancelToken,isCancel} = axios //CancelToken能为一次请求“打标识”
	let cancel
	btn.onclick = async()=>{
		// 每次点击按钮的时候都问一下外边是否有cancel 有没有值
		if(cancel){
			cancel()
		} 
		axios({
			url:'http://localhost:5000/test1?delay=3000',
			cancelToken:new CancelToken((c)=>{ //c是一个函数,调用c就可以关闭本次请求
				cancel = c
			})
		}).then(
			response => {console.log('成功了',response.data);},
			error => {
				if(isCancel(error)){
					//如果进入判断,证明:是用户取消了请求
					console.log('用户取消了请求,原因是:',error.message);
				}else{
					console.log('失败了',error);
				}
			}
		)
	}
	btn2.onclick = ()=>{
		cancel('任性,就是不要了')
	}
</script>
<button id="btn">点我获取测试数据</button><br/><br/>
<button id="btn2">取消请求</button><br/><br/>
<script type="text/javascript" >
	const btn = document.getElementById('btn')
	const btn2 = document.getElementById('btn2')
	const {CancelToken,isCancel} = axios //CancelToken能为一次请求“打标识”
	let cancel
	axios.interceptors.request.use((config)=>{
		if(cancel) cancel('取消了')
		config.cancelToken = new CancelToken((c)=> cancel= c)
		return config
	})
	axios.interceptors.response.use(
		response => {return response.data},
		error => {
			if(isCancel(error)){
				//如果进入判断,证明:是用户取消了请求
				console.log('用户取消了请求,原因是:',error.message);
			}else{
				console.log('失败了',error);
			}
			return new Promise(()=>{})
		}
	)
	btn.onclick = async()=>{
		const result = await axios.get('http://localhost:5000/test1?delay=3000')
		console.log(result);
	}
	btn2.onclick = ()=>{
		cancel('任性,就是不要了')
	}	
</script>

批量的发送请求

<script type="text/javascript" >
	const btn = document.getElementById('btn')
	btn.onclick = async()=>{
		axios.all([
			axios.get('http://localhost:5000/test1'),
			axios.get('http://localhost:5000/test2?delay=3000'),
			axios.get('http://localhost:5000/test3'),
		]).then(
			response => {console.log(response);},
			error => {console.log(error);}
		)
	}
</script>