1. axios封装
创建文件: axios.js
1.1 安装axios
npm install axios -S
1.2 针对不同环境设置baseurl
import axios from 'axios';
switch (process.env.NODE_ENV) {
case 'production':
axios.defaults.baseURL = 'http://121.89.205.189:3001/api';
break
default:
axios.defaults.baseURL = '/api';
break
}
1.3 一些其他默认设置
// 设置超时时间
axios.defaults.timeout = 5000;
// 设置跨域是否需要携带凭证
axios.defaults.withCredentials = false
// 设置判断是否响应成功的校验,3开头的代码一般都不在接口里面返回,一般都是资源类数据会返回
axios.defaults.validateStatus = status => {
return /^2|3\d{2}$/.test(status)
}
1.4 设置请求拦截器
// 设置请求拦截器,
axios.interceptors.request.use((config) => {
// 接收服务器返回的token,存储到本地,每次发送请求,都需要带上token
let token = localStorage.getItem('token')
// 普通模式
token && (config.headers.token = token)
// 进行token校验(JWT):
// token && (config.headers.Authorization = token)
// config需要返回
return config
}, error => {
// 请求错误的操作,返回报错信息
return Promise.reject(error)
})
1.5 设置响应拦截器
// 设置响应拦截器
/**
* response 包含内容:
* response: {
* data: 响应主体内容,axios 会自动生成,一般包括后端返回的数据,
* status: 服务器相应的状态码
* statusText: 响应状态码的描述,
* headers:服务器响应头
* config: 之前发送请求是发送给服务器的配置对象
* request: 原生的ajax对象
* }
*
*/
axios.interceptors.response.use((response) => {
if (response.data && response.data.code === '200') {
// 从接口中获取到token,保存到localstroage
if (response.data.data && response.data.data.token) {
localStorage.setItem("token", response.data.data.token);
}
return response.data;
} else {
// 错误处理
// 这里可以针对不同的code写一个switch
if (response.data.code === '10119') { // code: 10119: token失效
console.log('token失效,删除token')
localStorage.removeItem('token')
router.replace('/login')
// 下面的方法也可以实现跳转
// window.location.href = "/#/login"
}
// vant 弹窗展示错误信息给用户
Notify({
type: 'danger',
message: response.data.message
});
return response.data;
}
}, error => {
let {
response
} = error;
// 如果返回了response,证明服务器返回了结果,可以通过返回的状态码判断
if (response) {
switch (response.status) {
// 当前请求用户需要验证,一般为需要验证用户(未登录)
case 401:
break;
// 服务器接收到请求,但拒绝处理,一般为登录状态过期(token失效)
case 403:
localStorage.removeItem('token')
break;
// 找不到资源,
case 404:
break;
}
} else {
// 说明服务器连结果都没有返回,可能的原因有两种:
/**
* 1. 服务器崩掉了
* 2. 前端客户端断网状态
*/
if (!window.navigator.onLine) {
// 判断为断网,可以跳转到断网页面
return
} else {
console.log('!@#someerror')
return Promise.reject(error)
}
}
})
1.6 导出axios
export default axios
2. api 封装
创建文件: fetch.js
// 使用封装好的 axios (已设置默认选项)
import axios from './axios'
// 设置不缓存白名单
const whiteList = []
class Xhr {
// 单例模式
static getInstance() {
if (!this.instance) {
this.instance = new Xhr()
}
return this.instance
}
// 设置get请求缓存
constructor() {
this.cache = new Map()
}
/**
* 请求方法:
* get类型options携带params参数作为数据对象,
* post类型options携带data参数作为数据对象
*/
request(options) {
// 对get请求做一层缓存,允许post请求添加相同的数据
const {
method,
url,
params
} = options
let accessKey = url
// 如果是get请求且有参数,要缓存到参数,否则所有该url的请求都返回同一数据
// post 请求是添加数据不需要缓存
if (method === 'get' && params) {
for (let key in params) {
accessKey += key + params[key]
}
}
// 这里借鉴了vue源码的watcher
if (this.cache.has(accessKey) && !whiteList.includes(accessKey)) {
return Promise.resolve(this.cache.get(accessKey))
}
// promise.then还会返回一个promise
return axios(options).then((res) => {
if (method === 'get' && !this.cache.has(accessKey)) {
this.cache.set(accessKey, res)
}
return res
})
}
}
export default Xhr.getInstance()