使用异步 chrome.storage 时如何重构全局变量?

ade*_*hox 3 javascript google-chrome-extension chrome-extension-manifest-v3

要在迁移到 MV2 事件页面或 MV3 Service Worker 时删除持久 MV2 后台脚本中使用的全局变量,我找到的所有指南都只给出了一个示例,用几行设置替换单个全局变量,然后正在使用chrome.storage,但我仍然不清楚如何在更复杂的场景中使用它。

例如:

const activatedTabs = [];
let lastActiveTabInfo;
chrome.tabs.onActivated.addListener((activeInfo) => {
  if (activatedTabs.length === 0) {
    activatedTabs.push(activeInfo.tabId);
    lastActiveTabInfo = activeInfo;
  }
}
Run Code Online (Sandbox Code Playgroud)

如何重构上面的代码片段以使用chrome.storage和删除全局变量?

wOx*_*xOm 9

状态中变量的数量不会改变方法:

  1. 读取脚本开始时的状态
  2. 保存状态变化

您可以使用全局变量,只要您await对其进行初始化即可。

对于小数据(总共 1MB),请使用 chrome.storage.session,它位于内存中,即它不会写入磁盘,否则使用 chrome.storage.local。两者都只能存储 JSON 兼容的类型,即字符串、数字、布尔值、null、此类类型的数组/对象。还有用于 Blob 或 Uint8Array 的 IndexedDB。

单独的变量

let activatedTabs;
let lastActiveTabInfo;
let busy = chrome.storage.session.get().then(data => {
  activatedTabs = data.activatedTabs || [];
  lastActiveTabInfo = data.lastActiveTabInfo;
  busy = null;
});
const saveState = () => chrome.storage.session.set({
  activatedTabs,
  lastActiveTabInfo,
});

chrome.tabs.onActivated.addListener(async info => {
  if (!activatedTabs.length) {
    if (busy) await busy;
    activatedTabs.push(info.tabId);
    lastActiveTabInfo = info;
    await saveState();
  }
});
Run Code Online (Sandbox Code Playgroud)

具有属性的单个对象

const state = {
  activatedTabs: [],
  lastActiveTabInfo: null,
};
const saveState = () => chrome.storage.session.set({ state });
let busy = chrome.storage.session.get('state').then(data => {
  Object.assign(state, data.state);
  busy = null;
});

chrome.tabs.onActivated.addListener(async info => {
  if (!state.activatedTabs.length) {
    if (busy) await busy;
    state.activatedTabs.push(info.tabId);
    state.lastActiveTabInfo = info;
    await saveState();
  }
});
Run Code Online (Sandbox Code Playgroud)

如果您在后台脚本之外更改存储

...那么您需要订阅chrome.storage.onChanged事件。

笔记

请注意,如果您订阅 tabs.onActivated 等频繁事件,您的 Service Worker 可能每天会重新启动数百次,这比保持空闲的持久后台页面浪费更多的资源。Chromium 团队忽略了这个问题,但你不应该这样做,幸运的是,有一种方法可以通过延长软件生命周期来减少重新启动的次数。您仍然需要读取/保存状态,如图所示。