axios.create(config)
- 根据指定配置创建一个新的 axios, 也就就每个新 axios 都有自己的配置
- 新 axios 只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的
- 为什么要设计这个语法?
(1) 需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一
样, 如何处理
(2) 解决: 创建 2 个新 axios, 每个都有自己特有的配置, 分别应用到不同要
求的接口请求中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>axios.create()</title>
</head>
<body>
<!--
1). axios.create(config)
a. 根据指定配置创建一个新的axios, 也就就每个新axios都有自己的配置
b. 新axios只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的
c. 为什么要设计这个语法?
需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样, 如何处理
解决: 创建2个新axios, 每个都有自己特有的配置, 分别应用到不同要求的接口请求中
-->
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.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>
</body>
</html>
拦截器函数
对request拦截器采用unshift(堆栈)
request.hanlders.forEach(item=>chains.unshift(item))
对response拦截器采用push(队列)
response.hanlders.forEach(item=>chains.push(item))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>axios的处理链流程</title>
</head>
<body>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
<script>
/*
requestInterceptors: [{fulfilled1(){}, rejected1(){}}, {fulfilled2(){}, rejected2(){}}]
responseInterceptors: [{fulfilled11(){}, rejected11(){}}, {fulfilled22(){}, rejected22(){}}]
chain: [
fulfilled2, rejected2, fulfilled1, rejected1,
dispatchReqeust, undefined,
fulfilled11, rejected11, fulfilled22, rejected22
]
promise链回调: config
=> (fulfilled2, rejected2) => (fulfilled1, rejected1) // 请求拦截器处理
=> (dispatchReqeust, undefined) // 发请求
=> (fulfilled11, rejected11) => (fulfilled22, rejected22) // 响应拦截器处理
=> (onResolved, onRejected) // axios发请求回调处理
*/
// 添加请求拦截器(回调函数)
axios.interceptors.request.use(
config => {
console.log('request interceptor1 onResolved()')
return config
},
error => {
console.log('request interceptor1 onRejected()')
return Promise.reject(error);
}
)
axios.interceptors.request.use(
config => {
console.log('request interceptor2 onResolved()')
return config
},
error => {
console.log('request interceptor2 onRejected()')
return Promise.reject(error);
}
)
// 添加响应拦截器
axios.interceptors.response.use(
response => {
console.log('response interceptor1 onResolved()')
return response
},
function (error) {
console.log('response interceptor1 onRejected()')
return Promise.reject(error);
}
)
axios.interceptors.response.use(
response => {
console.log('response interceptor2 onResolved()')
return response
},
function (error) {
console.log('response interceptor2 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:/posts2')
.then(response => {
console.log('data', response.data)
})
.catch(error => {
console.log('error', error.message)
})
*/
</script>
</body>
</html>
- 说明: 调用 axios()并不是立即发送 ajax 请求, 而是需要经历一个较长的流程
- 流程: 请求拦截器2 => 请求拦截器1 => 发ajax请求 => 响应拦截器1 => 响
应拦截器 2 => 请求的回调 - 注意: 此流程是通过 promise 串连起来的, 请求拦截器传递的是 config, 响应
拦截器传递的是 response
取消请求
- 基本流程
配置 cancelToken 对象
缓存用于取消请求的 cancel 函数
在后面特定时机调用 cancel 函数取消请求
在错误回调中判断如果 error 是 cancel, 做相应处理 - 实现功能
点击按钮, 取消某个正在请求中的请求
在请求一个接口前, 取消前面一个未完成的请求
基本代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>取消请求</title>
</head>
<body>
<button onclick="getProducts1()">获取商品列表1</button><br>
<button onclick="getProducts2()">获取商品列表2</button><br>
<button onclick="cancelReq()">取消请求</button><br>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
<script>
let cancel // 用于保存取消请求的函数
function getProducts1() {
axios({
url: 'http://localhost:4000/products1',
cancelToken: new axios.CancelToken((c) => { // c是用于取消当前请求的函数
// 保存取消函数, 用于之后可能需要取消当前请求
cancel = c
})
}).then(
response => {
cancel = null
console.log('请求1成功了', response.data)
},
error => {
cancel = null
console.log('请求1失败了', error.message, error)
}
)
}
function getProducts2() {
axios({
url: 'http://localhost:4000/products2'
}).then(
response => {
console.log('请求2成功了', response.data)
},
error => {
cancel = null
console.log('请求2失败了', error.message)
}
)
}
function cancelReq() {
// alert('取消请求')
// 执行取消请求的函数
if (typeof cancel === 'function') {
cancel('强制取消请求')
} else {
console.log('没有可取消的请求')
}
}
</script>
</body>
</html>
在请求一个接口前, 取消前面一个未完成的请求:
function getProducts1() {
// 在准备发请求前, 取消未完成的请求
if (typeof cancel==='function') {
cancel('取消请求')
}
axios({
url: 'http://localhost:4000/products1',
cancelToken: new axios.CancelToken((c) => { // c是用于取消当前请求的函数
// 保存取消函数, 用于之后可能需要取消当前请求
cancel = c
})
}).then(
response => {
cancel = null
console.log('请求1成功了', response.data)
},
error => {
if (axios.isCancel(error)) {
// cancel = null
// 若不用这个,如果点三次第一个函数,会导致后面的第2个不能被取消,
// 因为第一个函数的error回调函数把cancel=null,此时正在执行第二个函数,
// 最后导致点击第三个函数时,判断的cancel=null,使得不能取消掉之前第二个函数
console.log('请求1取消的错误', error.message)
} else { // 请求出错了
cancel = null
console.log('请求1失败了', error.message)
}
}
)
}
使用拦截器优化代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>取消请求</title>
</head>
<body>
<button onclick="getProducts1()">获取商品列表1</button><br>
<button onclick="getProducts2()">获取商品列表2</button><br>
<button onclick="cancelReq()">取消请求</button><br>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
<script>
// 添加请求拦截器
axios.interceptors.request.use((config) => {
// 在准备发请求前, 取消未完成的请求
if (typeof cancel==='function') {
cancel('取消请求')
}
// 添加一个cancelToken的配置
config.cancelToken = new axios.CancelToken((c) => { // c是用于取消当前请求的函数
// 保存取消函数, 用于之后可能需要取消当前请求
cancel = c
})
return config
})
// 添加响应拦截器
axios.interceptors.response.use(
response => {
cancel = null
return response
},
error => {
if (axios.isCancel(error)) {// 取消请求的错误
// cancel = null
console.log('请求取消的错误', 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() {
// alert('取消请求')
// 执行取消请求的函数
if (typeof cancel === 'function') {
cancel('强制取消请求')
} else {
console.log('没有可取消的请求')
}
}
</script>
</body>
</html>