闽公网安备 35020302035485号
const cacheMap = new Map();封装一下调用接口的方法,调用时先走咱们缓存数据。
import axios, { AxiosRequestConfig } from 'axios'
// 堆代码 duidaima.com
// 先来一个简简单单的发送
export function sendRequest(request: AxiosRequestConfig) {
return axios(request)
}
然后加上咱们的缓存import axios, { AxiosRequestConfig } from 'axios'
import qs from 'qs'
const cacheMap = new Map()
interface MyRequestConfig extends AxiosRequestConfig {
needCache?: boolean
}
// 这里用params是因为params是 GET 方式穿的参数,我们的缓存一般都是 GET 接口用的
function generateCacheKey(config: MyRequestConfig) {
return config.url + '?' + qs.stringify(config.params)
}
export function sendRequest(request: MyRequestConfig) {
const cacheKey = generateCacheKey(request)
// 判断是否需要缓存,并且缓存池中有值时,返回缓存池中的值
if (request.needCache && cacheMap.has(cacheKey)) {
return Promise.resolve(cacheMap.get(cacheKey))
}
return axios(request).then((res) => {
// 这里简单判断一下,200就算成功了,不管里面的data的code啥的了
if (res.status === 200) {
cacheMap.set(cacheKey, res.data)
}
return res
})
}
然后调用const getArticleList = (params: any) =>
sendRequest({
needCache: true,
url: '/article/list',
method: 'get',
params
})
getArticleList({
page: 1,
pageSize: 10
}).then((res) => {
console.log(res)
})
这个部分就很简单,我们在调接口时给一个needCache的标记,然后调完接口如果成功的话,就会将数据放到cacheMap中去,下次再调用的话,就直接返回缓存中的数据。getArticleList({
page: 1,
pageSize: 10
}).then((res) => {
console.log(res)
})
getArticleList({
page: 1,
pageSize: 10
}).then((res) => {
console.log(res)
})
其实这样,就可以测出,我们的虽然设计了缓存,但是请求还是发送了两次,这是因为我们第二次请求发出时,第一次请求还没完成,也就没给缓存池里放数据,所以第二次请求没命中缓存,也就又发了一次。// 存储缓存当前状态,相当于挂牌子的地方
const statusMap = new Map<string, 'pending' | 'complete'>();
export function sendRequest(request: MyRequestConfig) {
const cacheKey = generateCacheKey(request)
// 判断是否需要缓存
if (request.needCache) {
if (statusMap.has(cacheKey)) {
const currentStatus = statusMap.get(cacheKey)
// 判断当前的接口缓存状态,如果是 complete ,则代表缓存完成
if (currentStatus === 'complete') {
return Promise.resolve(cacheMap.get(cacheKey))
}
// 如果是 pending ,则代表正在请求中,这里就等个三秒,然后再来一次看看情况
if (currentStatus === 'pending') {
return new Promise((resolve, reject) => {
setTimeout(() => {
sendRequest(request).then(resolve, reject)
}, 3000)
})
}
}
statusMap.set(cacheKey, 'pending')
}
return axios(request).then((res) => {
// 这里简单判断一下,200就算成功了,不管里面的data的code啥的了
if (res.status === 200) {
statusMap.set(cacheKey, 'complete')
cacheMap.set(cacheKey, res)
}
return res
})
}
试试效果getArticleList({
page: 1,
pageSize: 10
}).then((res) => {
console.log(res)
})
getArticleList({
page: 1,
pageSize: 10
}).then((res) => {
console.log(res)
})
// 定义一下回调的格式
interface RequestCallback {
onSuccess: (data: any) => void
onError: (error: any) => void
}
// 存放等待状态的请求回调
const callbackMap = new Map<string, RequestCallback[]>()
export function sendRequest(request: MyRequestConfig) {
const cacheKey = generateCacheKey(request)
// 判断是否需要缓存
if (request.needCache) {
if (statusMap.has(cacheKey)) {
const currentStatus = statusMap.get(cacheKey)
// 判断当前的接口缓存状态,如果是 complete ,则代表缓存完成
if (currentStatus === 'complete') {
return Promise.resolve(cacheMap.get(cacheKey))
}
// 如果是 pending ,则代表正在请求中,这里放入回调函数
if (currentStatus === 'pending') {
return new Promise((resolve, reject) => {
if (callbackMap.has(cacheKey)) {
callbackMap.get(cacheKey)!.push({
onSuccess: resolve,
onError: reject
})
} else {
callbackMap.set(cacheKey, [
{
onSuccess: resolve,
onError: reject
}
])
}
})
}
}
statusMap.set(cacheKey, 'pending')
}
return axios(request).then(
(res) => {
// 这里简单判断一下,200就算成功了,不管里面的data的code啥的了
if (res.status === 200) {
statusMap.set(cacheKey, 'complete')
cacheMap.set(cacheKey, res)
} else {
// 不成功的情况下删掉 statusMap 中的状态,能让下次请求重新请求
statusMap.delete(cacheKey)
}
// 这里触发resolve的回调函数
if (callbackMap.has(cacheKey)) {
callbackMap.get(cacheKey)!.forEach((callback) => {
callback.onSuccess(res)
})
// 调用完成之后清掉,用不到了
callbackMap.delete(cacheKey)
}
return res
},
(error) => {
// 不成功的情况下删掉 statusMap 中的状态,能让下次请求重新请求
statusMap.delete(cacheKey)
// 这里触发reject的回调函数
if (callbackMap.has(cacheKey)) {
callbackMap.get(cacheKey)!.forEach((callback) => {
callback.onError(error)
})
// 调用完成之后也清掉
callbackMap.delete(cacheKey)
}
// 这里要返回 Promise.reject(error),才能被catch捕捉到
return Promise.reject(error)
}
)
}
在判断到当前请求状态是pending时,将promise的resole与reject放入回调队列中,等待被触发调用。然后在请求完成时,触发对应的请求队列。getArticleList({
page: 1,
pageSize: 10
}).then((res) => {
console.log(res)
})
getArticleList({
page: 1,
pageSize: 10
}).then((res) => {
console.log(res)
})
getArticleList({
page: 1,
pageSize: 10
}).then(
(res) => {
console.log(res)
},
(error) => {
console.error(error)
}
)
getArticleList({
page: 1,
pageSize: 10
}).then(
(res) => {
console.log(res)
},
(error) => {
console.error(error)
}
)
OK,两个都失败了。(但是这里的error2早于error1打印,你知道是啥原因吗?)import axios, { AxiosRequestConfig } from 'axios'
import qs from 'qs'
// 存储缓存数据
const cacheMap = new Map()
// 存储缓存当前状态
const statusMap = new Map<string, 'pending' | 'complete'>()
// 定义一下回调的格式
interface RequestCallback {
onSuccess: (data: any) => void
onError: (error: any) => void
}
// 存放等待状态的请求回调
const callbackMap = new Map<string, RequestCallback[]>()
interface MyRequestConfig extends AxiosRequestConfig {
needCache?: boolean
}
// 这里用params是因为params是 GET 方式穿的参数,我们的缓存一般都是 GET 接口用的
function generateCacheKey(config: MyRequestConfig) {
return config.url + '?' + qs.stringify(config.params)
}
export function sendRequest(request: MyRequestConfig) {
const cacheKey = generateCacheKey(request)
// 判断是否需要缓存
if (request.needCache) {
if (statusMap.has(cacheKey)) {
const currentStatus = statusMap.get(cacheKey)
// 判断当前的接口缓存状态,如果是 complete ,则代表缓存完成
if (currentStatus === 'complete') {
return Promise.resolve(cacheMap.get(cacheKey))
}
// 如果是 pending ,则代表正在请求中,这里放入回调函数
if (currentStatus === 'pending') {
return new Promise((resolve, reject) => {
if (callbackMap.has(cacheKey)) {
callbackMap.get(cacheKey)!.push({
onSuccess: resolve,
onError: reject
})
} else {
callbackMap.set(cacheKey, [
{
onSuccess: resolve,
onError: reject
}
])
}
})
}
}
statusMap.set(cacheKey, 'pending')
}
return axios(request).then(
(res) => {
// 这里简单判断一下,200就算成功了,不管里面的data的code啥的了
if (res.status === 200) {
statusMap.set(cacheKey, 'complete')
cacheMap.set(cacheKey, res)
} else {
// 不成功的情况下删掉 statusMap 中的状态,能让下次请求重新请求
statusMap.delete(cacheKey)
}
// 这里触发resolve的回调函数
if (callbackMap.has(cacheKey)) {
callbackMap.get(cacheKey)!.forEach((callback) => {
callback.onSuccess(res)
})
// 调用完成之后清掉,用不到了
callbackMap.delete(cacheKey)
}
return res
},
(error) => {
// 不成功的情况下删掉 statusMap 中的状态,能让下次请求重新请求
statusMap.delete(cacheKey)
// 这里触发reject的回调函数
if (callbackMap.has(cacheKey)) {
callbackMap.get(cacheKey)!.forEach((callback) => {
callback.onError(error)
})
// 调用完成之后也清掉
callbackMap.delete(cacheKey)
}
return Promise.reject(error)
}
)
}
const getArticleList = (params: any) =>
sendRequest({
needCache: true,
baseURL: 'http://localhost:8088',
url: '/article/blogList',
method: 'get',
params
})
export function testApi() {
getArticleList({
page: 1,
pageSize: 10
}).then(
(res) => {
console.log(res)
},
(error) => {
console.error('error1:', error)
}
)
getArticleList({
page: 1,
pageSize: 10
}).then(
(res) => {
console.log(res)
},
(error) => {
console.error('error2:', error)
}
)
}
最后