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

Chrome扩展:条件性添加/移除请求拦截监听器遇无限循环求助

解决Chrome扩展中webRequest监听器移除导致的无限循环问题

看起来你遇到了Chrome扩展里webRequest监听器管理的典型问题——函数引用不匹配导致监听器无法正确移除,进而引发逻辑混乱。我来帮你拆解问题并给出修复方案:

问题根源分析

  1. 函数引用不唯一:你在chrome.storage.sync.get的回调函数内部定义了removeJS,每次触发storage变化时,都会创建一个全新的removeJS函数实例。当你调用removeListener时,传入的这个新函数和之前addListener时传入的函数引用完全不同,浏览器找不到要移除的监听器,导致旧的监听器一直堆积。
  2. 逻辑顺序错误:不管当前status是true还是false,你都先执行了addListener,这会导致即使想移除监听器,也先新增了一个,进一步加剧了监听器堆积的问题,最终引发站点加载异常甚至无限循环。
  3. 闭包捕获旧值:removeJS里的data.status是闭包捕获的get回调中的旧值,当storage状态更新后,拦截逻辑并不会使用新的状态,导致拦截行为和预期不一致。

修复后的完整代码

// 全局维护当前拦截状态,确保拦截逻辑使用最新值
let currentInterceptStatus = false;
// 标记监听器是否已添加,避免重复操作
let listenerIsAdded = false;

// 定义全局的拦截函数,确保引用唯一
function blockDevtestScripts(details) {
  if (currentInterceptStatus) {
    return { cancel: true };
  }
  // 状态为false时,不拦截,直接返回undefined即可
}

// 统一处理监听器的添加/移除逻辑
function updateRequestListener(shouldIntercept) {
  if (shouldIntercept && !listenerIsAdded) {
    chrome.webRequest.onBeforeRequest.addListener(
      blockDevtestScripts,
      { urls: ["https://devtest.com*"], types: ["script"] },
      ["blocking"]
    );
    listenerIsAdded = true;
    console.log('已启用devtest.com脚本拦截');
  } else if (!shouldIntercept && listenerIsAdded) {
    chrome.webRequest.onBeforeRequest.removeListener(blockDevtestScripts);
    listenerIsAdded = false;
    console.log('已禁用devtest.com脚本拦截');
  }
}

// 初始化:获取初始状态并设置监听器
chrome.storage.sync.get('status', (data) => {
  currentInterceptStatus = data.status ?? false;
  updateRequestListener(currentInterceptStatus);
});

// 监听storage状态变化,更新全局状态和监听器
chrome.storage.onChanged.addListener((changes, namespace) => {
  // 只处理sync空间下的status变化
  if (changes.status && namespace === 'sync') {
    const { oldValue, newValue } = changes.status;
    console.log(`拦截状态更新:旧值=${oldValue},新值=${newValue}`);
    currentInterceptStatus = newValue;
    updateRequestListener(newValue);
  }
});

关键改动说明

  1. 全局函数与状态:把拦截函数blockDevtestScripts和状态变量提到全局作用域,确保每次添加/移除的是同一个函数引用,同时保证拦截逻辑使用最新的状态值。
  2. 监听器状态标记:新增listenerIsAdded变量,避免重复添加监听器或尝试移除不存在的监听器,这是解决监听器堆积的核心。
  3. 统一逻辑函数:拆分出updateRequestListener函数,把添加/移除监听器的逻辑集中管理,代码更清晰也更易维护。
  4. 初始化处理:插件启动时主动获取一次storage状态,设置初始的监听器状态,避免直到storage变化才生效的问题。

这样修改后,就能正确根据storage的状态切换拦截/放行逻辑,不会再出现监听器堆积和无限循环的问题,站点也能正常加载了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:59:41