目录
axios-拦截器
作用: 请求发送之前,响应回来之后执行一些 公共 的逻辑
不难发现, 这其实就是一个顺序链表能实现的,把请求拦截器的函数推在前面, api请求的核心方法放在中间, 响应拦截器放在数组后面,遍历执行链表就实现了拦截器的顺序执行过程。
拦截器的作用
a. 统计api从发起请求到返回数据需要的时间
b. 配置公共的请求头,加载弹窗等
c. 对响应状态码做拦截,比入后端返回400或500的状态码, 返回对应错误信息
- 注册之后,调用接口
- 请求发送时--》执行请求拦截器--》服务器
- 服务器响应内容--》执行响应拦截器--》接收数据
请求拦截器-基本写法:
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么,比如: 统一设置token
// 通过config可以获取请求的设置,比如headers可以获取(修改)请求头
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
axios请求拦截器-统一设置token
通过请求拦截器统一设置token
需求:
- 通过请求拦截器统一设置token
- 设置一次之后后续调用接口不用单独设置
核心步骤:
- 添加请求拦截器
- 统一设置token
- 移除首页对应逻辑
关键代码:
- commons.js
// 添加请求拦截器
// 统一携带token
axios.interceptors.request.use(function (config) {
// 可以通过headers,查看+设置请求头
// config.headers['info'] = 'itheima666'
// 每次发送请求,都会执行这个回调函数
// console.log(config)
// 在发送请求之前做些什么,比如: 统一设置token
const token = localStorage.getItem('token')
// token存在,才携带
if (token) {
config.headers['Authorization'] = token
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
- index.js
// 首页-统计数据
async function getData() {
try {
// 调用接口(登录成功之后才可以调用)
const res = await axios({
url: '/dashboard',
// 通过axios请求拦截器统一携带
})
const overview = res.data.data.overview
// 渲染数据
Object.keys(overview).forEach(key => {
document.querySelector(`.${key}`).innerText = overview[key]
})
} catch (error) {
// 首页-登录状态过期
// 判断token失效(状态码401):token过期,token被篡改
// console.dir(error)
if (error.response.status === 401) {
// 删除缓存并提示用户
localStorage.removeItem('username')
localStorage.removeItem('token')
// 使用普通用户可以理解的方式提示他们
showToast('请重新登录')
// 返回登录页
setTimeout(() => {
location.href = 'login.html'
}, 1500)
}
}
}
响应拦截器-基本写法:
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么,比如: 数据剥离
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么: 比如统一处理token失效
return Promise.reject(error);
});
axios响应拦截器-统一处理token失效
axios响应拦截器-统一处理token失效
需求:
- 通过 axios响应拦截器-统一处理token失效
核心步骤:
- 添加响应拦截器
- 统一处理token失效
- 移除首页对应逻辑
关键代码:
- common.js
// 添加响应拦截器
// 统一处理token过期
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
return response;
}, function (error) {
// console.dir(error)
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么: 比如统一处理token失效
// 统一处理token失效
if (error.response.status === 401) {
// 弹框提示用户
showToast('请重新登录')
// 删除缓存
localStorage.removeItem('token')
localStorage.removeItem('username')
// 返回登录页
setTimeout(() => {
location.href = 'login.html'
}, 1500)
}
return Promise.reject(error);
});
- index.js
// 首页-统计数据
async function getData() {
// 调用接口(登录成功之后才可以调用)
const res = await axios({
url: '/dashboard',
// 通过axios请求拦截器统一携带
})
const overview = res.data.data.overview
// 渲染数据
Object.keys(overview).forEach(key => {
document.querySelector(`.${key}`).innerText = overview[key]
})
}
axios响应拦截器-数据剥离
axios响应拦截器-数据剥离
需求:
- axios响应拦截器-数据剥离
- 页面中使用数据时少写一个data
核心步骤:
- 剥离data属性(响应拦截器)
- 调整数据使用逻辑(登录,注册,首页)
关键代码:
- commons.js
// 添加响应拦截器
// 统一处理token过期
// 数据剥离
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么,比如: 数据剥离
// 剥离data属性,页面中少写.data属性,直接可以获取到数据
return response.data;
}, function (error) {
// console.dir(error)
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么: 比如统一处理token失效
// 统一处理token失效
if (error.response.status === 401) {
// 弹框提示用户
showToast('请重新登录')
// 删除缓存
localStorage.removeItem('token')
localStorage.removeItem('username')
// 返回登录页
setTimeout(() => {
location.href = 'login.html'
}, 1500)
}
return Promise.reject(error);
});
- index.js:移除多余的.data
// 首页-统计数据
async function getData() {
// 调用接口(登录成功之后才可以调用)
const res = await axios({
url: '/dashboard',
// 通过axios请求拦截器统一携带
})
const overview = res.data.overview
// 渲染数据
Object.keys(overview).forEach(key => {
document.querySelector(`.${key}`).innerText = overview[key]
})
}
- register.js:移除多余的.data,try中
document.querySelector('#btn-register').addEventListener('click', async () => {
// 1. 收集并校验数据
const form = document.querySelector('.register-form')
const data = serialize(form, { empty: true, hash: true })
// console.log(data)
const { username, password } = data
console.log(username, password)
// 非空校验
if (username === '' || password === '') {
showToast('用户名和密码不能为空')
return
}
// 长度校验
if (username.length < 8 || username.length > 30 || password.length < 6 || password.length > 30) {
showToast('用户名的长度为8-30,密码的长度为6-30')
return
}
// 2. 数据提交
try {
// .post 请求方法 post,参数1:请求URL,参数2:提交的数据
const res = await axios.post('/register', { username, password })
// console.log(res)
showToast(res.message)
} catch (error) {
// console.dir(error)
showToast(error.response.data.message)
}
})
- login.js:移除多余的.data,try中
document.querySelector('#btn-login').addEventListener('click', async () => {
// 1. 收集并校验数据
const form = document.querySelector('.login-form')
const data = serialize(form, { empty: true, hash: true })
console.log(data)
const { username, password } = data
// 非空判断
if (username === '' || password === '') {
showToast('用户名和密码不能为空')
return
}
// 格式判断
if (username.length < 8 || username.length > 30 || password.length < 6 || password.length > 30) {
showToast('用户名长度8-30,密码长度6-30')
return
}
// 2. 提交数据
try {
const res = await axios.post('/login', { username, password })
// console.log(res)
showToast(res.message)
// 3. 缓存响应数据
localStorage.setItem('token', res.data.token)
localStorage.setItem('username', res.data.username)
// 4. 跳转首页
// 延迟一会在跳转,让提示框显示
setTimeout(() => {
// login.html和index.html的相对关系
location.href = './index.html'
}, 1500)
} catch (error) {
// console.dir(error)
showToast(error.response.data.message)
}
})