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)
}
#如有帮助,恭请采纳!
您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!设置缓存数据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");
}
},
}
});
不知道你这个问题是否已经解决, 如果还没有解决的话:我可以给出一些可能导致缓存无法正常工作的原因,并给出一些解决方案:
缓存的实现有误:对于cache函数的实现,代码中没有给出完整的实现细节,可以先检查代码实现是否正确,并且检查cache函数是否有被正确调用。
缓存的key值问题:需要注意缓存的key值特别是字符串值的比较是应该是严格比较(即使用全等符“===”),否则可能会出现一些不可预料的问题。
缓存的时效问题:需要考虑缓存的时效性,避免缓存数据过时而影响结果。可以根据具体情况设置缓存过期时间并在缓存时标记时间,检查是否过期后再从缓存中读取数据。
缓存的大小限制问题:如果缓存的大小没有限制,可能会导致内存溢出等问题。可以设置缓存的最大大小,并在缓存时判断是否超出最大大小限制,如果超出则删除旧数据。
其他原因:还有可能是缓存的具体使用方法或者缓存对象的特性(比如引用类型)等问题导致缓存无法正常工作。需要结合具体的使用场景进行分析并进行相应的修改调整。
针对以上可能出现的问题,可以根据具体情况进行进一步分析和调试,逐步修改并优化缓存实现,以达到优化代码执行效率的目的。