修复清除缓存显示"已释放约0.0MB",与实际清理量不符
现象:设置-清除缓存确认后,无论Cache Storage里实际有多少数据,展示的"已释放约 X MB"几乎总是0.0,即使清理动作本身(caches.delete)确实生效(caches.keys()清理后 变为空数组)。 根因:原实现在caches.delete()前后各调用一次navigator.storage.estimate(),用两次 usage之差算释放量。实测确认Chrome的storage.estimate()不会同步反映Cache Storage的 删除——caches.keys()已经确认清空后,estimate()仍继续报告删除前的usageDetails.caches 数值,实测滞后超过500ms未刷新。人为塞入一个2MB的Cache Storage测试项复现:删除成功 但"已释放"显示0.0MB;塞入3MB项验证修复后正确显示3.0MB。 修法:不再依赖storage.estimate()的前后差值,改成删除前逐个遍历所有Cache Storage条目、读取每个response的真实blob大小并累加,直接得到本次会话即将删除的 真实字节数,不受浏览器存储统计滞后影响。 验证:npm run build:dev后浏览器实测——(1) 无缓存数据时点击"清除缓存",正确显示 0.0MB且弹层能正常从"清空缓存"态切到"缓存已清理"态、点"完成"可关闭;(2) 用JS人为写入 2MB/3MB测试用Cache Storage条目,分别清理后弹层准确显示2.0MB/3.0MB,且caches.keys() 确认条目已被真实删除。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
cd092108c2
commit
552c891cc3
@@ -367,20 +367,40 @@ function CacheClear({onToast, onClose}) {
|
||||
const confirm = async () => {
|
||||
setBusy(true);
|
||||
try {
|
||||
// navigator.storage/caches can be entirely absent (private browsing in some browsers, older
|
||||
// WebViews) rather than just rejecting -- referencing a missing global throws synchronously,
|
||||
// which a bare .catch() on the call below can't catch (it never gets that far), so without
|
||||
// this check the whole confirm() throws, `done` never becomes true, and the "已完成" state is
|
||||
// never reached even though the button correctly stops spinning via `finally`.
|
||||
const hasStorageEstimate = typeof navigator !== 'undefined' && navigator.storage && navigator.storage.estimate;
|
||||
// Was a before/after navigator.storage.estimate() diff around the caches.delete() call --
|
||||
// measured live (see this round's regression notes): estimate() does NOT reflect a deletion
|
||||
// synchronously, Chrome keeps reporting the pre-delete `usageDetails.caches` figure for well
|
||||
// over 500ms after `caches.keys()` already comes back empty. Every real run of this button
|
||||
// therefore computed `before - after` from two numbers that were still identical, landing on
|
||||
// "已释放约 0.0 MB" even when megabytes of real thumbnails/temp files were actually deleted --
|
||||
// confirmed by seeding a 2MB dummy Cache Storage entry and watching this path report 0.0 MB
|
||||
// freed for it. Summing each entry's real blob size before deleting it sidesteps the OS-level
|
||||
// storage accounting lag entirely -- the number shown is exactly what this run deleted, not an
|
||||
// estimate that may or may not have caught up yet.
|
||||
// caches can be entirely absent (private browsing in some browsers, older WebViews) rather than
|
||||
// just rejecting -- referencing a missing global throws synchronously, which a bare .catch() on
|
||||
// the call below can't catch (it never gets that far), so without this check the whole
|
||||
// confirm() throws, `done` never becomes true, and the "已完成" state is never reached even
|
||||
// though the button correctly stops spinning via `finally`.
|
||||
const hasCaches = typeof caches !== 'undefined';
|
||||
const before = hasStorageEstimate ? (await navigator.storage.estimate().catch(() => ({usage: 0}))).usage || 0 : 0;
|
||||
let freedBytes = 0;
|
||||
if (hasCaches) {
|
||||
const keys = await caches.keys();
|
||||
for (const key of keys) {
|
||||
const cache = await caches.open(key);
|
||||
const requests = await cache.keys();
|
||||
for (const request of requests) {
|
||||
const response = await cache.match(request);
|
||||
if (!response) continue;
|
||||
// clone() -- match() gives back the one real (non-clonable-twice) body for this entry;
|
||||
// reading .blob() off it directly would leave nothing for a concurrent reader of the
|
||||
// same cache, however unlikely that is here.
|
||||
freedBytes += (await response.clone().blob().catch(() => null))?.size || 0;
|
||||
}
|
||||
}
|
||||
await Promise.all(keys.map(k => caches.delete(k)));
|
||||
}
|
||||
const after = hasStorageEstimate ? (await navigator.storage.estimate().catch(() => ({usage: 0}))).usage || 0 : 0;
|
||||
setFreed(Math.max(0, before - after));
|
||||
setFreed(freedBytes);
|
||||
setDone(true);
|
||||
} catch (err) {
|
||||
onToast(err.message || '清理失败,请重试');
|
||||
|
||||
Reference in New Issue
Block a user