js cache缓存不了的问题请教


const cacheName = 'my-cache';


export async function cacheFile(key: string, response: Response): Promise<void> {
    try {
        const cache: Cache = await caches.open(cacheName);
        const clonedResponse = response.clone(); // 克隆响应对象
        await cache.put(key, clonedResponse);
        // // 将响应体转换为可重复读取的 Blob 对象
        // const blob = await response.blob();
        // const clonedResponse = new Response(blob, response);
        // await cache.put(key, clonedResponse); // 将克隆的响应对象放入缓存

        console.log(`PDF 已缓存: ${key}`);
    } catch (error) {
        console.error('缓存操作发生错误:', error);
    }
}



export async function getCachedFile(key: string): Promise<Response | null> {
    try {
        const cache: Cache = await caches.open(cacheName);
        const response: Response | undefined = await cache.match(key);
        if (response) {
            console.log(`从缓存中获取 PDF: ${key}`);
            return response;
        }
        console.log(`未找到缓存的 PDF: ${key}`);
        return null;
    } catch (error) {
        console.error('缓存操作发生错误:', error);
        return null;
    }
}
为什么我把文件写入缓存时,报错:
           const fileName = url!.substring(url!.lastIndexOf('/') + 1);
            const cachedFile = await getCachedFile(fileName)
            let response:Response
            if(cachedFile){
               response = cachedFile
            } else {
                response = await fetch(serverURL + url!,{cache: 'force-cache'});
                cacheFile(fileName,response)
            }
            // const response = cachedFile ?? await fetch(serverURL + url!,{cache: 'force-cache'});
           
            pdfData = await response.arrayBuffer();

一直报错如下:
缓存操作发生错误: TypeError: Failed to execute 'clone' on 'Response': Response body is already used
    at cacheFile (cacheFun.ts:7:41)


这个错误的原因是因为 Response 对象在使用后就会被关闭。你通过 await response.arrayBuffer() 来获取响应体,这表示该响应已被使用过了。
当你将这个响应对象传递给 cacheFile 函数时,它尝试克隆响应对象,以便将其放入缓存中。由于该响应对象在之前已经被使用过了,因此无法再次进行克隆操作,从而导致错误。
解决这个问题的方法是,在使用响应体后,将其克隆一份,并对克隆的响应对象进行操作,而不是直接使用原始响应对象。
虽然你已经在 cacheFile 函数中对响应对象进行了克隆,但是你没有在具体使用响应对象的地方进行克隆。你可以将这段代码修改为:

const fileName = url!.substring(url!.lastIndexOf('/') + 1);
const cachedFile = await getCachedFile(fileName)
let response: Response
if (cachedFile) {
    response = cachedFile.clone(); // 克隆响应对象
} else {
    response = await fetch(serverURL + url!, { cache: 'force-cache' });
    cacheFile(fileName, response.clone()); // 将克隆的响应对象放入缓存
}
pdfData = await response.arrayBuffer();

以上的不是很重要 ,重要的是给个采纳加关注 下个问题不迷路谢谢谢谢

参考GPT作答。
这个错误是因为在执行 cacheFile(fileName, response) 之后,您尝试再次使用相同的 response 对象。然而,Response 对象的响应主体只能被消耗(consumed)一次,在第一次使用后就会变为不可用状态。

为了解决这个问题,您可以通过使用 response.clone() 来创建一个新的副本,而不是直接使用原始的 response 对象,例如下:

const fileName = url!.substring(url!.lastIndexOf('/') + 1);
const cachedFile = await getCachedFile(fileName);
let response: Response;
if (cachedFile) {
  response = cachedFile;
} else {
  response = await fetch(serverURL + url!, { cache: 'force-cache' });
  cacheFile(fileName, response.clone()); // 创建副本并进行缓存操作
}

pdfData = await response.arrayBuffer();

通过使用 response.clone(),您可以在其中一个副本上进行缓存操作,而在另一个副本上获取 arrayBuffer 数据,从而避免了该错误。

这个错误通常是因为在调用cacheFile函数之前已经使用了response对象。删除行const clonedResponse = response.clone();,直接使用原始的response进行缓存操作。这样就不会在克隆之后的响应对象中读取response的响应体而导致错误。具体地,将以下代码:

const clonedResponse = response.clone(); // 克隆响应对象
await cache.put(key, clonedResponse);

改为:

await cache.put(key, response);

这样就可以避免出现该错误。

if(cachedFile){  
   response = cachedFile  
} else {  
   response = await fetch(serverURL + url!,{cache: 'force-cache'});  
   cacheFile(fileName,response)  
}

报错释义:类型错误:未能对“Response”执行“clone”:已使用响应正文,在cacheFile(cacheFun.ts:7:41)
结合报错释义分析:当 cachedFile 存在时,你将 cachedFile 分配给 response。但是,在 else 语句中,你再次使用 response 来引用 fetch 调用的响应。这可能会导致问题,因为 fetch 调用返回的响应对象可能已经被用于其他用途,导致上面的错误消息。
思路:将 fetch 调用的响应对象分配给 fetchResponse 变量,然后使用 fetchResponse 变量来调用 arrayBuffer() 方法并将结果分配给 response 变量。这将确保 fetch 调用的响应对象没有被错误地重用。
修正代码如下:

if(cachedFile){  
   response = cachedFile  
} else {  
   const fetchResponse = await fetch(serverURL + url!,{cache: 'force-cache'});  
   response = await fetchResponse.arrayBuffer();  
   cacheFile(fileName,fetchResponse)  
}

#如有帮助,恭请采纳!
您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632

设置缓存数据js源代码cache.js
可以看看

$.extend($, {
    Cache : {
        userData: false,
        supportLocalStorage: typeof localStorage == 'object' ? true : false,
        name: location.hostname,
 
        init: function () {
            if ( $.Cache.supportLocalStorage )
                return false;
            if ( !$.Cache.userData ) {
                try {
                    $.Cache.userData = document.createElement('INPUT');
                    $.Cache.userData.type = "hidden";
                    $.Cache.userData.style.display = "none";
                    $.Cache.userData.addBehavior("#default#userData");
                    document.body.appendChild($.Cache.userData);
                    var expires = new Date();
                    expires.setDate(expires.getDate() + 365);
                    $.Cache.userData.expires = expires.toUTCString();
                } catch (e) {
                    return false;
                }
            }
            return true;
        },
 
        set: function (key, value, expire) {
            if ( typeof value == 'object' ) {
                value = JSON.stringify(value);
            }
            if ( expire == undefined )
                expire = 0;
 
            if ( $.Cache.init() ) {
                $.Cache.userData.load($.Cache.name);
                $.Cache.userData.setAttribute(key, value);
                if ( expire > 0 ) {
                    var timestamp = Date.parse(new Date());
                    var expiration = timestamp + expire;
                    $.Cache.userData.setAttribute(key + "_EXPIRE", expiration);
                }
                $.Cache.userData.save($.Cache.name);
            } else {
                localStorage.setItem(key, value);
                if ( expire > 0 ) {
                    var timestamp = Date.parse(new Date());
                    var expiration = timestamp + expire;
                    localStorage.setItem(key + "_EXPIRE", expiration);
                }
            }
        },
 
        get: function (key) {
            var val;
            var timestamp = Date.parse(new Date());
            if ( $.Cache.init() ) {
                $.Cache.userData.load($.Cache.name);
                val = $.Cache.userData.getAttribute(key);
                var expiration = $.Cache.userData.getAttribute(key + "_EXPIRE");
                if ( expiration != null && expiration != undefined && expiration > 0  ) {
                    if ( expiration < timestamp) {
                        $.Cache.userData.removeAttribute(key);
                        $.Cache.userData.removeAttribute(key + "_EXPIRE");
                        return undefined;
                    }
                }
            } else {
                val = localStorage.getItem(key);
                var expiration = localStorage.getItem(key + "_EXPIRE");
                if ( expiration != null && expiration != undefined && expiration > 0 ) {
                    if ( expiration < timestamp) {
                        localStorage.removeItem(key);
                        localStorage.removeItem(key + "_EXPIRE");
                        return undefined;
                    }
                }
            }
            if ( val == null || val == undefined || val == "" )
                return undefined;
            if ( val.indexOf("{") == 0 || val.indexOf("[") == 0 ) {
                return JSON.parse(val);
            }
            return val;
        },
        del : function(key) {
            if ( $.Cache.init() ) {
                $.Cache.userData.load($.Cache.name);
                $.Cache.userData.removeAttribute(key);
                $.Cache.userData.removeAttribute(key + "_EXPIRE");
            } else {
                localStorage.removeItem(key);
                localStorage.removeItem(key + "_EXPIRE");
            }
        },
    }
});

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    我可以给出一些可能导致缓存无法正常工作的原因,并给出一些解决方案:

    1. 缓存的实现有误:对于cache函数的实现,代码中没有给出完整的实现细节,可以先检查代码实现是否正确,并且检查cache函数是否有被正确调用。

    2. 缓存的key值问题:需要注意缓存的key值特别是字符串值的比较是应该是严格比较(即使用全等符“===”),否则可能会出现一些不可预料的问题。

    3. 缓存的时效问题:需要考虑缓存的时效性,避免缓存数据过时而影响结果。可以根据具体情况设置缓存过期时间并在缓存时标记时间,检查是否过期后再从缓存中读取数据。

    4. 缓存的大小限制问题:如果缓存的大小没有限制,可能会导致内存溢出等问题。可以设置缓存的最大大小,并在缓存时判断是否超出最大大小限制,如果超出则删除旧数据。

    5. 其他原因:还有可能是缓存的具体使用方法或者缓存对象的特性(比如引用类型)等问题导致缓存无法正常工作。需要结合具体的使用场景进行分析并进行相应的修改调整。

    针对以上可能出现的问题,可以根据具体情况进行进一步分析和调试,逐步修改并优化缓存实现,以达到优化代码执行效率的目的。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^