需求背景
这个页面有些接口是反复调用了,针对已经请求过的,不要再像后端发送请求了,前端自己做缓存吧
分析
- 前端针对请求过的数据存在内存里面;
- 缓存在内存里的数据只是在当前页面有用,页面卸载时需要清除数据。
实现
方法1:在页面中使用Map缓存数据
import React, { useEffect, useState } from "react";
import axios from 'axios';
import { Button, Space, Spin, Table } from 'antd';
axios.defaults.baseURL = 'https://api.github.com';
const columns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
}
]
// !定义在函数组件外,是需要在页面卸载的时候清除的,否则针对单页面再次进来是有影响的
const cacheMap = new Map();
const Demo = () => {
const [loading, setLoading] = useState<boolean>(false);
const [list, setList] = useState<Array<any>>([])
const fetchList = async (username :string) => {
setLoading(true);
// 实现缓存
// 键值:这里用得是请求的参数,因为参数这里能保证是唯一的
const cacheResult = cacheMap.get(username)
// 有了,就直接拿来用
if (cacheResult) {
setList(cacheResult)
setLoading(false);
return
}
const res: any = await axios.request({
url: `users/${username}/repos`,
method: 'get'
})
// 不存在在缓存中,就存一份
cacheMap.set(username, res.data);
setLoading(false);
setList(res.data);
}
const getUserInfo = (username: string) => {
fetchList(username)
}
useEffect(() => {
return () => {
// 卸载
cacheMap.clear();
}
}, [])
return (
<Spin spinning={loading}>
<Space size="small">
<Button onClick={() => getUserInfo('Believel')}>Believle</Button>
<Button onClick={() => getUserInfo('zhangxiang958')}>zhangxiang958</Button>
<Button onClick={() => getUserInfo('tanggd')}>tanggd</Button>
<Button onClick={() => getUserInfo('baozouai')}>baozouai</Button>
</Space>
<Table dataSource={list} columns={columns} rowKey='id' />
</Spin>
)
};
export default Demo;
这种方式是直接写在业务代码中的,而且
if(cacheResult)内的处理逻辑,与外面有些逻辑是重复的
方法2:从业务代码中抽离出来,缓存请求接口
cacheService.ts
import axios from 'axios'
export interface CacheServiceState {
store: any;
}
class CacheService {
store: any;
constructor() {
this.store = {};
}
async fetch(params: any) {
// 最好保证请求参数每次是唯一的,否则的话不适用这种缓存键
const fetchCacheKey = JSON.stringify(params);
if (this.store[fetchCacheKey]) {
return this.store[fetchCacheKey]
}
const result = await axios.request(params);
this.store[fetchCacheKey] = result;
return result;
}
clearCache() {
this.store = {};
}
}
const CacheServiceInstance = new CacheService();
export default CacheServiceInstance;
demo.tsx
import React, { useEffect, useState } from "react";
import axios from 'axios';
import { Button, Space, Spin, Table } from 'antd';
axios.defaults.baseURL = 'https://api.github.com';
import CacheServiceInstance from './cacheService';
const columns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
}
]
const Demo = () => {
const [loading, setLoading] = useState<boolean>(false);
const [list, setList] = useState<Array<any>>([])
const fetchList = async (username :string) => {
setLoading(true);
const res: any = await CacheServiceInstance.fetch({
url: `users/${username}/repos`,
method: 'get'
})
setLoading(false);
setList(res.data);
}
const getUserInfo = (username: string) => {
fetchList(username)
}
useEffect(() => {
return () => {
// 清除缓存
CacheServiceInstance.clearCache();
}
}, [])
return (
<Spin spinning={loading}>
<Space size="small">
<Button onClick={() => getUserInfo('Believel')}>Believle</Button>
<Button onClick={() => getUserInfo('zhangxiang958')}>zhangxiang958</Button>
<Button onClick={() => getUserInfo('tanggd')}>tanggd</Button>
<Button onClick={() => getUserInfo('baozouai')}>baozouai</Button>
</Space>
<Table dataSource={list} columns={columns} rowKey='id' />
</Spin>
)
};
export default Demo;
实现与业务代码分离,降低代码耦合度
总结
coding时多思考,少抱怨,加油!