文章目录
Axios
1.基础准备:
请求报文:
请求行(method,url),
请求头(比如Host:www.baidu.com,Cookie:xxx,Content-Type:application/x-www-form-urlencoded 或 application/json或 multipart/form-data:文件上传格式),
请求体(格式一:username=tom&age=18;格式二:{“username”:"tom})
响应报文:
响应状态行 (state:200 状态码对应的文本)
多个响应头 (Content-Type:响应体类型 Set-Cookie)
响应体 (图片、等)
请求方式:(9种)
常用 get:请求数据 post:添加数据 put:更新数据 delete:删除数据
携带参数 query:?id=1 过滤数组得到对象 和 param:/1 直接得到对象
2.ajax
什么是ajax?
ajax请求是一个特殊的http请求,对服务器端来说没区别,区别在于浏览器端
浏览器端:xhr或fetch发送的才是ajax请求
ajax与一般请求区别
一般请求:浏览器一般会直接显示响应体,也就是我们平常说的刷新、跳转页面
ajax请求:浏览器不会对界面进行任何更新操作,只是调用监视的回调函数并传入响应的相关数据
ps:可以查查 XHR api
3.axios
1.介绍
axios的特点:
- 有请求/响应拦截器:axios.interceptors.request/response.use()
- 数据转换
- 返回的是promise对象
- 批量执行多个异步请求 axios.all(promise)
- 可以取消请求
axios语法:略
开发中通常会对axios二次封装
2.手动封装ajax请求,实现最简单的axios
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
function axios({
url,
method = 'GET',
params = {},
data = {}
}) {
//返回一个promise对象
return new Promise((resolve, reject) => {
method = method.toUpperCase();
//处理query参数(拼接到url上) id=1&name=abc
let queryString = ''
Object.keys(params).forEach(key => {
queryString += `${key}=${params[key]}&`
})
if (queryString) {
//去除最后多的&
queryString = queryString.substring(0, queryString.length - 1)
url += '?' + queryString
}
//执行异步ajax请求
let request = new XMLHttpRequest()
//初始化,建立连接,true是异步,false是同步
request.open(method, url, true)
//发送请求
if (method === 'GET' || method === 'DELETE') {
request.send()
} else if (method === 'POST' || method === 'PUT') {
//告诉服务器请求体的格式为json
request.setRequestHeader('Content-Type', 'application/json;charset=utf-8')
request.send(JSON.stringify(data))
}
//绑定状态改变的监听
//因为send()是异步的,所以监听写在这也行,肯定是先绑定监听再发请求
request.onreadystatechange = function () {
if (request.readyState !== 4) {
return
}
//如果响应状态码在[200,300)之间表示成功,否则失败
const {status, statusText} = request
// 成功
if (status >= 200 && status < 300) {
//准备结果对象
const response = {
data: JSON.stringify(request.response),
status,
statusText
}
resolve(response)
} else {
// 失败
reject(new Error('request error,错误码' + status + statusText))
}
}
})
}
axios({
url: '/xxx',
})
</script>
</body>
</html>
3.注意点
axios和axios.creat()出来的instance是一个函数并非实例对象,这样可以给不同端口发请求
const instance = axios.create({
baseURL: 'http://localhost:4000',
timeout: 1000
})
//使用instance发请求
instance({
url: '/index'
})
const instance2 = axios.create({
baseURL: 'http://localhost:3000',
timeout: 1000
})
//使用instance发请求
instance2({
url: '/index'
})
4.拦截器
拦截器(回调函数) 注意:请求拦截器是先添加的后执行:响应拦截器是先写先执行
axios.interceptors.request.use(
config => {
return config
},
error => {
return Promise.reject(error)
})
//发送get请求
axios.get('接口')
.then(response => {
})
.catch(error => {
console.log(error)
})
5.请求取消
let cancel //用于保存取消请求的函数
axios({
url: '',
cancelToken: new axios.CancelToken(function (c) { //c是用于取消当前请求的函数
cancel = c
})
}).then(response => {
cancel = null
...
},
error => {
cancel = null
...
})
if (typeof cancel === 'function') {
cancel()
} else {
console.log('没有可取消的请求')
}
请求取消案例: 两个请求,当点击第二个时取消第一个请求,
细节:错误的回调要将出错和取消请求的回调分开处理,取消的话不用使cancel函数为null,
原因:同步异步代码的执行顺序,当点第三次的时候取消不了第二次,因为后面的会先检查cancel是不是函数,如果是就给他覆盖了,最后导致取消函数失效
//定义一个函数cancel
let cancel = null
axios.interceptors.request.use(
config => {
if (cancel instanceof Function) {
cancel()
}
config.cancelToken = new axios.CancelToken(function (c) { //c是用于取消当前请求的函数
cancel = c
})
return config
},
error => {
if (axios.isCancel(error)) {
console.log('取消');
} else {
cancel = null
console.log('请求出错');
}
}
)
function a1() {
axios({
url: 'xxx',
/*cancelToken: new axios.CancelToken(function (c) { //c是用于取消当前请求的函数
cancel = c
})*/
}).then(
response => {
console.log(response);
}
).catch(
error => {
cancel = null
console.log(error);
})
}
function a2() {
axios({
url: 'xxx',
/*cancelToken: new axios.CancelToken(function (c) { //c是用于取消当前请求的函数
cancel = c
})*/
}).then(
response => {
console.log(response);
}
).catch(
error => {
if (axios.isCancel(error)) {
//如果是取消的话就不用把cancel设置为null,否则会影响下一下的取消
console.log('取消');
} else {
cancel = null
console.log('请求出错');
}
})
}
4.深入理解一些
axios与Axios的关系
1.从语法上来说,axios不是Axios的实例,因为axios是一个函数
2.从功能上来说,axios是Axios的实例,因为具有Axios的所有属性(defaults,interceptor),有Axios的原型上的方法
3.axios实际上是Axios.prototype.request方法.bind得来的
axios.js
var axios = creatInstance(config)
function creatInstance(config) {
let context = new Axios(config)
//绑定request方法
let instance = bind(Axios.prototype.request, context)
//调用extend方法copy Axios原型上的方法和Axios的属性到instance
instance.extend(...)
return instance
}
axios.creat = ...
axios.creatToken=...
axios和instance的异同
同:
都是Axios.prototype.request函数通过修改this得来的
异:
instance没有axios后添加的creatToken,cancel,creat等方法
axios工作流程:
request串:
chain数组:[请求拦截器(先写后执行,unshift),dispatchRequest(),undefined 响应拦截器(先写先执行,因为在相应拦截器数组中是push)],通过promise链串联起来
dispatchRequest(config)
转换请求数据 => 调用xhrAdapter()发请求 => 请求返回后转换响应数据,返回promise
xhrAdapter(config)
创建xhr对象,根据config进行设置,发送特定请求,并接收响应数据,返回promise