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

Chrome扩展:解决自动重定向引发内容脚本重复触发问题

解决Chrome扩展在YouTube重定向时多次触发倒计时的问题

问题根源

当打开带ab_channel参数的YouTube链接时,网站会自动重定向并移除该参数,导致chrome.tabs.onUpdated事件多次触发(每次页面加载完成都会触发一次),背景脚本多次向内容脚本发送消息,最终生成多个倒计时实例,出现按钮提前弹出、显示异常的问题。

解决方案

从背景脚本的事件防抖和内容脚本的单例控制两方面入手,确保重定向过程中只执行一次扩展流程。

1. 背景脚本:添加防抖逻辑,避免重复发送消息

修改background.js,为每个tab设置防抖定时器,短时间内重复触发时取消之前的任务,只执行最后一次:

// background.js
const tabTimers = {}; // 存储每个tab的防抖定时器ID

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (tab.active && changeInfo.status === "complete" && tab.url.startsWith("https://www.youtube.com")) {
        // 清除当前tab之前的防抖定时器
        if (tabTimers[tabId]) {
            clearTimeout(tabTimers[tabId]);
        }

        // 设置新的防抖定时器,1000ms内重复触发则覆盖
        tabTimers[tabId] = setTimeout(() => {
            // 尝试向内容脚本发送消息
            try {
                chrome.tabs.sendMessage(tabId, { greeting: "start intervention" });
            } catch {
                setTimeout(() => {
                    chrome.tabs.sendMessage(tabId, { greeting: "start intervention" });
                }, 3000);
            }
            // 执行后清除该tab的定时器记录
            delete tabTimers[tabId];
        }, 1000); // 防抖延迟,可根据实际调整,建议1000ms左右
    }
});

2. 内容脚本:确保单一定时器和DOM实例

修改content-script.js,全局存储定时器ID,每次收到消息时先清除之前的定时器,同时统一管理DOM元素的创建与销毁:

// content-script.js
let downloadTimer = null; // 全局存储定时器ID

chrome.runtime.onMessage.addListener((request, sender) => {
    if (request.greeting === "start intervention") {
        // 1. 清除之前的定时器,防止多个实例运行
        if (downloadTimer) {
            clearInterval(downloadTimer);
            downloadTimer = null;
            console.log("已清除旧定时器");
        }

        // 2. 移除现有DOM元素
        const existingBanner = document.getElementById("time-management-banner");
        if (existingBanner) {
            existingBanner.remove();
            console.log("time-management-banner 已移除");
        }

        // 3. 创建新的banner和定时器元素
        const banner = document.createElement("div");
        banner.id = 'time-management-banner';
        banner.className = 'time-management';
        banner.innerHTML = "<b>Stop and take a deep breath.</b>";
        document.body.appendChild(banner);

        const timer = document.createElement("div");
        timer.className = "time-management";
        timer.id = "time-management-timer";
        banner.appendChild(timer);

        // 4. 启动新的倒计时
        let secondsLeft = 3;
        downloadTimer = setInterval(() => {
            if (secondsLeft <= 0) {
                clearInterval(downloadTimer);
                downloadTimer = null;

                // 移除现有按钮
                const buttons = document.getElementsByClassName("time-management-button");
                while (buttons.length > 0) {
                    buttons[0].parentNode.removeChild(buttons[0]);
                }

                // 创建并插入按钮
                const proceed_button = document.createElement("button");
                const exit_button = document.createElement("button");
                proceed_button.textContent = "继续浏览";
                exit_button.textContent = "离开";
                proceed_button.className = "time-management-button";
                exit_button.className = "time-management-button";

                banner.appendChild(proceed_button);
                banner.appendChild(exit_button);

                // 补充按钮事件(根据需求自行添加)
                // proceed_button.addEventListener('click', () => { /* 逻辑 */ });
                // exit_button.addEventListener('click', () => { window.location.href = 'https://example.com' });
            } else {
                timer.textContent = secondsLeft;
                secondsLeft -= 1;
            }
        }, 1000);
    }
});

关键改进点

  • 背景脚本防抖:通过tabTimers对象跟踪每个tab的定时器,确保短时间内重复触发时只执行最后一次消息发送,避免多次调用内容脚本。
  • 内容脚本单例控制:全局存储定时器ID,每次收到消息先清除旧定时器,确保同一时间只有一个倒计时在运行;统一DOM元素的销毁逻辑,避免残留元素冲突。
  • 简化DOM操作:移除冗余的元素检查步骤,直接调用remove(),代码更简洁可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:34:53