到这里,相信大家已经能够熟练运用缓存来加速甚至避免网络请求,然而浏览器为每个应用所分配的存储空间是有限的,因此我们往往需要删除部分缓存来释放存储空间,至于需要删除哪些缓存,这正是本章需要讲解的内容。
由于
CacheStorage是针对请求/响应类型对象的存储方案,它适用于网址可寻址(比如脚本、样式、图片、HTML 等)资源,基于此我们将使用 IndexedDB 来存储并处理缓存的过期信息,下文中所使用的类 DB 为 IndexedDB API 的简单封装,具体代码可在示例中获得,为节省篇幅,此处不再列出。
# 常见算法
# FIFO
该算法的核心思想是:如果一个数据最先加入缓存中,那么在存储空间不足时应该删除加入时间较久远的数据。

代码实现如下:
class CacheExpirationDB extends DB {
constructor(cacheName, maxAgeSeconds) {
super('CacheExpiration', 1, event => {
const db = event.target.result;
const objStore = db.createObjectStore('CacheExpiration', { keyPath: 'id' });
objStore.createIndex('timestamp', 'timestamp', { unique: false });
});
this._cacheName = cacheName;
this._maxAgeSeconds = maxAgeSeconds;
}
/**
* 去除 `url` 中的 `hash`(比如将:`/detail/12#hash` 转换为 `/detail/12`)
*/
_normalizeURL(baseUrl) {
const url = new URL(baseUrl, location);
url.hash = '';
return url.pathname;
}
/**
* 根据 url 生成记录 id
*/
_getId(url) {
return `${this._cacheName}|${this._normalizeURL(url)}`;
}
async set(url, timestamp) {
const expireEntries = await this.expireEntries(timestamp);
await this.write('put', 'CacheExpiration', {
id: this._getId(url),
cacheName: this._cacheName,
url: this._normalizeURL(url),
timestamp
});
return expireEntries;
}
async expireEntries(timestamp) {
const minTimestamp = timestamp - this._maxAgeSeconds;
const entriesToDelete = await this._transaction(
'CacheExpiration', 