使用 Dexie.js 实现 API 数据缓存,减少网络请求
1. 为什么要使用 Dexie.js 进行 API 数据缓存?
在前端开发中,频繁的 API 请求会带来以下问题:
- 性能问题:多次请求相同数据会增加网络带宽消耗,导致页面加载变慢。
- 服务器压力:频繁请求相同的数据会增加后端服务器的负担。
- 离线支持:如果用户的网络不稳定或处于离线状态,仍然需要访问最近获取的数据。
使用 Dexie.js(一个基于 IndexedDB 的轻量级封装库)可以高效地缓存 API 数据,减少不必要的请求,优化应用的性能。
2. Dexie.js 简介
Dexie.js 是一个基于 IndexedDB 的数据库库,提供了更简单的 API 来管理客户端存储。它具有:
- 支持 Promise 和 async/await
- 提供索引和查询优化
- 支持事务
- 自动版本管理
安装:
npm install dexie
3. API 数据缓存的基本思路
使用 Dexie.js 进行 API 缓存的大致流程如下:
- 创建数据库和表,定义存储数据的结构。
- 检查本地缓存,如果数据存在且不过期,直接返回。
- 如果本地没有数据或数据已过期,向 API 发起请求,并将数据存储到 IndexedDB 中。
- 提供缓存失效策略,例如基于时间的缓存(TTL, Time-to-Live)。
4. 实现 API 数据缓存
4.1 初始化 Dexie 数据库
import Dexie from 'dexie';// 创建数据库
const db = new Dexie("ApiCacheDB");// 定义数据表结构
db.version(1).stores({cache: 'key, timestamp', // 以 key 作为主键,存储时间戳用于过期检查
});// 定义数据表类型
interface CacheEntry {key: string;data: any;timestamp: number;
}
4.2 读取缓存数据
const getCachedData = async (key: string, maxAge: number = 5 * 60 * 1000) => {const entry = await db.table("cache").get(key);if (entry) {const now = Date.now();if (now - entry.timestamp < maxAge) {console.log("Using cached data:", key);return entry.data;} else {console.log("Cache expired:", key);await db.table("cache").delete(key); // 移除过期数据}}return null;
};
4.3 存储 API 数据
const setCachedData = async (key: string, data: any) => {await db.table("cache").put({ key, data, timestamp: Date.now() });
};
4.4 使用缓存封装 API 请求
const fetchWithCache = async (key: string, url: string, maxAge: number = 5 * 60 * 1000) => {const cachedData = await getCachedData(key, maxAge);if (cachedData) return cachedData;try {const response = await fetch(url);const data = await response.json();await setCachedData(key, data);return data;} catch (error) {console.error("API request failed:", error);throw error;}
};
4.5 在 Vue 组件中使用
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { fetchWithCache } from "@/utils/cache"; // 假设缓存逻辑封装在 utils/cache.tsconst posts = ref([]);onMounted(async () => {try {posts.value = await fetchWithCache("posts", "https://jsonplaceholder.typicode.com/posts");} catch (error) {console.error("Failed to load posts:", error);}
});
</script><template><div><h1>Posts</h1><ul><li v-for="post in posts" :key="post.id">{{ post.title }}</li></ul></div>
</template>
5. 进阶优化策略
5.1 增加缓存数据的自动清理机制
定期清理旧数据,防止 IndexedDB 过度膨胀:
const clearOldCache = async (maxAge: number = 24 * 60 * 60 * 1000) => {const now = Date.now();const oldEntries = await db.table("cache").where("timestamp").below(now - maxAge).toArray();for (const entry of oldEntries) {await db.table("cache").delete(entry.key);}
};
在应用启动时执行:
clearOldCache();
5.2 允许用户手动刷新数据
在 Vue 组件中增加手动刷新按钮:
<button @click="refreshData">刷新数据</button><script setup lang="ts">
const refreshData = async () => {await db.table("cache").delete("posts");posts.value = await fetchWithCache("posts", "https://jsonplaceholder.typicode.com/posts");
};
</script>
5.3 预缓存数据
在用户打开应用时,预先缓存一些常用数据:
onMounted(() => {fetchWithCache("posts", "https://jsonplaceholder.typicode.com/posts");
});
6. 结论
使用 Dexie.js 进行 API 缓存可以有效减少网络请求,提高应用的性能,同时还能在离线模式下提供更好的用户体验。关键策略包括:
- 数据缓存检查:优先从 IndexedDB 读取数据,避免重复请求。
- 数据缓存存储:存储最新 API 数据,并记录时间戳。
- 缓存过期策略:定期清理过期数据,保证存储不会无限增长。
- 手动刷新:允许用户手动刷新缓存数据。
这种方法适用于大多数 Vue/React/Node.js Web 应用,特别是对 API 访问频繁的场景,比如:
- 新闻/博客列表
- 用户资料
- 商品信息
使用 Dexie.js 提供的 IndexedDB 作为存储,既能减少 API 负载,又能提升前端应用的响应速度,实现更好的用户体验。