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

Chrome扩展中点击事件仅第二次触发的问题排查

问题原因及修复方案

核心问题分析

  1. 动态元素事件绑定失效:注入的HTML元素是动态添加到DOM中的,直接绑定元素事件时,元素尚未存在,导致首次点击无响应。
  2. 变量重复声明报错:全局作用域内重复使用let声明visitedCount、visitSpeed等变量,引发运行时错误,中断事件逻辑执行。
  3. IndexedDB初始化异步问题:createDB()是异步操作,首次点击时db可能未初始化完成,调用addUser时会抛出错误,导致事件流程中断。
  4. 定时器未清理:点击Stop后,已设置的setTimeout仍会继续执行,影响状态判断。

具体修复步骤

1. 改用事件委托绑定点击事件

针对动态注入的元素,将事件绑定到document或稳定的父元素上:

// 替换原事件绑定代码
$(document).on("click", "#counter--status", function (e) {
  if ($(this).text() === "Start") {
    $(this).text("Stop");

    $(data).each(function (index, username) {
      let eUsername = username;
      setTimeout(function () {
        if ($("#counter--status").text() == "Stop") {
          $("#container--profiles--visited").html(visitedCount);
          var percentRound = (
            (visitedCount / data.length) *
            100 *
            1.025
          ).toFixed(0);
          $("#container--bottom--status").html(
            "Remaining: " + percentRound + "% - Visiting: " + eUsername
          );

          if (jQuery.inArray(eUsername, visited) == -1) {
            visited.push(eUsername);
            visitedCount += 1;
            fetch("https://www.theurls.com", {
              headers: {
                "x-api-key": "XXX",
                "x-session-id": "XXX",
              },
            })
              .then((response) => response.json())
              .then((data) => addUser(eUsername));
          }
        }
      }, visitSpeed * index);
    });
  } else {
    $("#counter--status").text("Start");
    $("#counter--count").html("");
  }
});

2. 清理重复的变量声明

删除全局作用域内重复的let声明,保留一份变量定义:

// 保留顶部的变量声明,删除后续重复部分
data = ["test", "test2", "test3"];
let ids = [];
let visitedCount = 0;
let visitSpeed = 1000;
let visited = [];
let db = null;
const mVisitDB = new Map();

// 注入HTML
injectedhtml = `
    <div id="container--start-counter">
        <span id="counter--status">
            Start
        </span>
        <span id="counter--count"></span>
    </div>`;

// 仅赋值,不再重复声明
data = [];

3. 确保IndexedDB初始化完成后再处理事件

修改createDB(),添加初始化完成回调,避免db未就绪时调用相关方法:

function createDB() {
  const request = indexedDB.open("VisitDB", 1);

  request.onupgradeneeded = function(event) {
    db = event.target.result;
    // 创建所需的对象仓库
    if (!db.objectStoreNames.contains("username")) {
      db.createObjectStore("username", { keyPath: "user" });
    }
    if (!db.objectStoreNames.contains("blocked_user")) {
      db.createObjectStore("blocked_user", { keyPath: "user" });
    }
  };

  request.onsuccess = function(event) {
    db = event.target.result;
    // DB初始化完成后再绑定事件
    bindCounterEvent();
  };

  request.onerror = function(event) {
    console.error("IndexedDB初始化失败:", event.target.error);
  };
}

// 封装事件绑定逻辑
function bindCounterEvent() {
  $(document).on("click", "#counter--status", function (e) {
    // 原事件逻辑
  });
}

4. 添加定时器清理逻辑

点击Stop时,清除所有未执行的定时器,避免后续逻辑继续运行:

let timeoutIds = []; // 新增存储定时器ID的数组

$(document).on("click", "#counter--status", function (e) {
  if ($(this).text() === "Start") {
    $(this).text("Stop");
    timeoutIds = []; // 清空之前的定时器ID

    $(data).each(function (index, username) {
      let eUsername = username;
      const timeoutId = setTimeout(function () {
        if ($("#counter--status").text() == "Stop") {
          // 原逻辑...
        }
      }, visitSpeed * index);
      timeoutIds.push(timeoutId); // 保存定时器ID
    });
  } else {
    $("#counter--status").text("Start");
    $("#counter--count").html("");
    // 清除所有未执行的定时器
    timeoutIds.forEach(id => clearTimeout(id));
    timeoutIds = [];
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:25:25