项目场景:
项目中的图片地址添加了Authorization,需要通过请求blob格式再展示。
问题描述
考虑到图片比较大,每次请求都挺耗时,考虑优先使用前端缓存。
解决方案:
利用 axios 的拦截器和 CancelToken,在请求拦截器中根据请求地址判断(只缓存get请求)缓存池中是否已存在数据,如果存在并且没有过期,则取消请求,响应拦截器中的 error 捕获到 source.cancel 发送的缓存数据,通过 axios.isCancel(error) 来判断是否为手动取消的请求(true)还是正常接口错误(false),为 true 则返回缓存数据。同时响应拦截器中的 response 需要将请求返回的数据存入缓存池中,并设置过期时间。
创建 requestCache.js :
// requestCache.js
import axios from 'axios'
// 定义一个缓存池用来缓存数据
const cache = {}
const EXPIRE_TIME = 5 * 60 * 1000
// 利用axios的cancelToken来取消请求
const CancelToken = axios.CancelToken
const service = axios.create({
baseURL: ''
})
// 请求拦截器中用于判断数据是否存在以及过期 未过期直接返回
service.interceptors.request.use(config => {
// 如果需要缓存--考虑到并不是所有接口都需要缓存的情况
if (config.cache) {
const source = CancelToken.source()
config.cancelToken = source.token
// 去缓存池获取缓存数据
const data = cache[config.url]
// 获取当前时间戳
const expire_time = getExpireTime()
// 判断缓存池中是否存在已有数据 存在的话 再判断是否过期
// 未过期 source.cancel会取消当前的请求 并将内容返回到拦截器的err中
if (data && expire_time - data.expire < EXPIRE_TIME) {
source.cancel(data)
}
}
return config
})
// 响应拦截器中用于缓存数据 如果数据没有缓存的话
service.interceptors.response.use(
response => {
// 只缓存get请求
if (response.config.method === 'get' && response.config.cache) {
// 缓存数据 并将当前时间存入 方便之后判断是否过期
const data = {
expire: getExpireTime(),
data: response.data
}
cache[`${response.config.url}`] = data
}
return response
},
error => {
// 请求拦截器中的source.cancel会将内容发送到error中
// 通过axios.isCancel(error)来判断是否返回有数据 有的话直接返回给用户
if (axios.isCancel(error)) {
return Promise.resolve(error.message)
}
// 如果没有的话 则是正常的接口错误 直接返回错误信息给用户
return Promise.reject(error)
}
)
// 获取当前时间
function getExpireTime() {
return new Date().getTime()
}
export default service
调用方式:
import requestCache from '@/utils/requestCache'
async getImageObjectUrl(url) {
const response = await requestCache
.get(url, {
responseType: 'blob',
headers: {
'Authorization': `Bearer ${this.token}`
},
cache: true // true 则启用缓存
})
return response.data ? URL.createObjectURL(response.data) : ''
}

21万+

被折叠的 条评论
为什么被折叠?



