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

await fetch未等待致模板重复加载,缓存机制失效问题

解决模板缓存重复请求问题

问题根源

短时间多次调用loadFile时,第一个请求还未完成(未将内容存入缓存),后续调用检查缓存找不到对应URL,就会重复发起fetch请求。此外代码还存在两个明显问题:

  • 全局变量content会在并发调用时被覆盖,导致结果混乱
  • catch的错误处理写法错误,无法正确捕获异常

解决方案

核心思路是缓存正在进行的请求Promise,而非仅缓存已加载完成的内容。第一次发起请求时,将请求的Promise存入缓存,后续调用直接等待该Promise完成,避免重复请求。

修改步骤

  1. 用Map替代数组作为缓存容器,查找效率更高、结构更清晰
  2. 缓存项存储两种状态:已加载完成的内容,或是正在进行的请求Promise
  3. 移除全局content变量,让loadFile返回对应内容的Promise,确保调用者能正确获取结果
  4. 修正错误处理逻辑,请求失败时清理缓存,避免后续调用一直等待失败请求
  5. 保证同一URL的请求仅发起一次,后续调用复用已有请求或缓存内容

完整修改代码

// 用Map存储缓存,key为模板URL,value为已加载内容或正在请求的Promise
const cache = new Map();

this.loadFile = async function(url) {
    // 检查缓存是否存在
    if (cache.has(url)) {
        const cachedItem = cache.get(url);
        // 如果是Promise,说明请求正在进行,直接等待完成
        if (cachedItem instanceof Promise) {
            console.log("Waiting for ongoing request...");
            await cachedItem;
        } else {
            console.log("Cached!");
        }
        // 返回缓存的内容
        return cache.get(url);
    }

    // 无缓存,发起请求
    console.log("Fetching...");
    // 创建请求Promise并先存入缓存
    const requestPromise = fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error(`请求失败,状态码:${response.status}`);
            }
            return response.text();
        })
        .then(content => {
            // 请求完成后,将缓存中的Promise替换为实际内容
            cache.set(url, content);
            console.log("content");
            return content;
        })
        .catch(error => {
            // 请求失败,移除缓存中的失败Promise,允许后续重新请求
            cache.delete(url);
            console.error("加载失败:", error);
            throw error; // 抛出错误让调用者处理
        });

    cache.set(url, requestPromise);
    // 等待请求完成并返回结果
    return await requestPromise;
};

this.render = function(url) {
    // 从缓存中获取对应URL的内容(可根据需求调整逻辑)
    return cache.get(url) || '';
};

调用方式

依然使用await调用,但现在能保证同一URL仅发起一次请求:

await Tpl.loadFile(chrome.runtime.getURL("view/widget.html"));
let content = Tpl.render(chrome.runtime.getURL("view/widget.html"));

内容的提问来源于stack exchange,提问作者FMaz008

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:01:16