You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 6项目中Safari无法删除Cache API缓存文件问题求助

Safari中Cache API删除缓存失败并触发Quota Exceeded的解决方案

我之前也遇到过Safari对Cache API的兼容性问题,咱们来一步步解决你碰到的这个问题:

问题根源分析

Safari的Cache API实现和Chrome存在不少差异,其中最关键的两点是:

  1. 删除整个缓存时,Safari不会立即释放对应的存储空间,系统回收资源的延迟会导致再次保存时触发配额超限。
  2. 对缓存条目的引用管理更严格,直接删除缓存实例可能无法彻底清理关联的资源。

针对性解决方案

1. 删除特定缓存条目而非整个缓存

你的removeFile()方法是直接删除整个缓存实例,这在Safari里容易出现资源残留。改成先打开缓存,删除目标URL对应的条目,再按需删除空缓存:

removeFile() {
  this.resetValues();
  caches.open(this.id).then((cache) => {
    // 先删除指定URL的缓存条目
    return cache.delete(this.url).then((isEntryDeleted) => {
      console.log("Specific file entry removed:", isEntryDeleted);
      // 如果缓存为空,再删除整个缓存实例
      return cache.keys().then((remainingKeys) => {
        if (remainingKeys.length === 0) {
          return caches.delete(this.id).then((isCacheDeleted) => {
            console.log("Empty cache instance deleted:", isCacheDeleted);
          });
        }
      });
    }).then(() => {
      this.status = 'File removed';
    });
  }).catch((error: Error) => {
    this.errorMessage = error.message;
    console.error('Error removing file from cache :(', error);
  });
}

2. 克隆Fetch响应再存入缓存

Safari对Fetch响应的一次性使用限制更严格,直接存入缓存可能导致响应资源未被正确释放。修改saveFile()方法,克隆响应后再存入:

saveFile() {
  this.resetValues();
  caches.open(this.id).then((cache) => {
    // 先检查缓存是否已存在该文件,避免重复占用空间
    return cache.match(this.url).then((existingEntry) => {
      if (existingEntry) {
        this.status = 'File already exists in cache';
        return Promise.resolve();
      }
      return fetch(this.url).then((response) => {
        console.log("fetch complete", response);
        // 克隆响应后存入缓存
        return cache.put(this.url, response.clone()).then((data) => {
          console.log("cache complete", data)
          this.status = 'File saved';
        });
      });
    });
  }).catch((error: Error) => {
    this.errorMessage = error.message;
    console.error('Error caching file!', error);
  });
}

3. 额外优化:主动清理过期/无用缓存

如果你的应用会缓存多个文件,建议定期清理无用缓存,避免Safari的配额被占满:

async cleanupOldCaches() {
  const cacheNames = await caches.keys();
  for (const name of cacheNames) {
    // 根据你的缓存命名规则,过滤需要保留的缓存
    if (!name.startsWith(this.id)) {
      await caches.delete(name);
      console.log("Cleaned up old cache:", name);
    }
  }
}

验证步骤

按照这个修改后,再按你的重现步骤测试:

  • 打开Safari,点击"Save file"
  • 点击"Remove file",此时会先删除条目,再清理空缓存
  • 再次点击"Save file",应该不会再触发Quota Exceeded错误

内容的提问来源于stack exchange,提问作者Daniel Muñoz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:21:57