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

如何在Chrome扩展后台与弹窗脚本间持久化动态计数数据?

解决方案:Chrome扩展弹窗计数持久化与关闭检测

一、修复弹窗关闭检测的代码问题

你之前的代码仅在后台监听连接,但弹窗未主动发起连接,导致onDisconnect无法触发。需同时修改弹窗脚本与后台脚本:

后台脚本(background.js)

let port = null;

chrome.runtime.onConnect.addListener(function(externalPort) {
  port = externalPort;
  console.log("弹窗已连接");
  
  externalPort.onDisconnect.addListener(function() {
    console.log("弹窗已关闭");
    // 触发后台继续计数逻辑
    resumeCounting();
  });
});

// 供弹窗获取当前计数的消息监听
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'GET_COUNT') {
    sendResponse({ count: currentCount });
  }
});

弹窗脚本(popup.js)

// 弹窗加载时主动连接后台
const port = chrome.runtime.connect();

// 请求初始计数并渲染
chrome.runtime.sendMessage({ type: 'GET_COUNT' }, (response) => {
  renderCount(response.count);
});

// 弹窗打开后切换为本地计数
let localCount;
chrome.runtime.sendMessage({ type: 'PAUSE_COUNT' }, (response) => {
  localCount = response.count;
  setInterval(() => {
    localCount++;
    renderCount(localCount);
  }, 1000);
});

function renderCount(count) {
  document.getElementById('count').textContent = count;
}

二、更高效的计数方案(避免每秒写存储)

无需每秒更新存储,只需在后台记录两个核心值:

  • lastCount:上次暂停时的计数值
  • pauseTime:上次暂停的时间戳

核心逻辑:

  1. 弹窗打开时:后台计算从pauseTime到当前的时间差(秒数),与lastCount相加得到实时值,随后暂停后台计数,切换为弹窗本地每秒递增
  2. 弹窗关闭时:弹窗将当前本地计数同步到后台,后台更新lastCount与pauseTime

后台脚本完整实现

let lastCount = 0;
let pauseTime = Date.now();
let intervalId = null;

// 恢复后台计数(弹窗关闭时触发)
function resumeCounting() {
  if (intervalId) clearInterval(intervalId);
  intervalId = setInterval(() => {
    const elapsed = Math.floor((Date.now() - pauseTime) / 1000);
    lastCount += elapsed;
    pauseTime = Date.now();
  }, 1000);
}

// 暂停后台计数(弹窗打开时触发)
function pauseCounting() {
  if (intervalId) clearInterval(intervalId);
  const elapsed = Math.floor((Date.now() - pauseTime) / 1000);
  lastCount += elapsed;
  pauseTime = Date.now();
  return lastCount;
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  switch(request.type) {
    case 'GET_COUNT':
      const elapsed = Math.floor((Date.now() - pauseTime) / 1000);
      sendResponse({ count: lastCount + elapsed });
      break;
    case 'PAUSE_COUNT':
      const current = pauseCounting();
      sendResponse({ count: current });
      break;
    case 'UPDATE_COUNT':
      lastCount = request.count;
      pauseTime = Date.now();
      sendResponse({ success: true });
      break;
  }
});

// 监听弹窗断开连接,触发恢复计数
chrome.runtime.onConnect.addListener((port) => {
  port.onDisconnect.addListener(() => {
    resumeCounting();
  });
});

弹窗脚本完整实现

let localCount = 0;
let intervalId = null;

// 加载时获取初始计数并启动本地计数
chrome.runtime.sendMessage({ type: 'GET_COUNT' }, (response) => {
  localCount = response.count;
  renderCount(localCount);
  intervalId = setInterval(() => {
    localCount++;
    renderCount(localCount);
  }, 1000);
});

// 弹窗关闭前同步计数到后台
window.addEventListener('beforeunload', () => {
  chrome.runtime.sendMessage({ type: 'UPDATE_COUNT', count: localCount });
  if (intervalId) clearInterval(intervalId);
});

function renderCount(count) {
  document.getElementById('count').textContent = count;
}

三、关键说明

  • 用时间戳计算差值替代每秒写存储,仅在弹窗打开/关闭时更新存储,大幅降低操作频率
  • 弹窗连接+beforeunload事件双重保障,确保关闭时计数能同步到后台
  • 若需浏览器重启后仍保留计数,只需在后台启动时读取一次存储,关闭时写入一次即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:52:50