【问题标题】:How to use localStorage or an alternative in Manifest v3如何在 Manifest v3 中使用 localStorage 或替代方案
【发布时间】:2022-01-13 23:18:34
【问题描述】:

我正在尝试将 Chrome 扩展程序切换为使用 Manifest v3。

除了我使用localStorage的地方之外,我什么都得到了:

if (localStorage.getItem(lastchecked[0]) < Date.now() - 2500000000) {
    localStorage.setItem(lastchecked[0], Date.now());
} else {
    const remover = Date.now() - 2500000000;
    Object.entries(localStorage).forEach(([k, v]) => {
        if (v < remover) {
            delete localStorage[k];
        }
    });
}

这是我得到的错误:

ReferenceError: localStorage is not defined

据我所知,这是因为我将扩展程序从使用背景 script 切换为使用 service worker,这似乎无法访问 localStorage

除了localStorage 之外,还有什么简单的方法可以将它切换为使用其他东西,因为它不可用?

【问题讨论】:

标签: google-chrome google-chrome-extension chrome-extension-manifest-v3


【解决方案1】:

localStorage 根据规范在服务工作者中不可用。原因是因为它提供同步访问,所以必须在启动 JS 环境之前完整读取它,这可能需要一些时间,这与环境本身的启动时间(~50ms)相当,以防存储包含几兆字节(最大为 5MB)。

Service Worker 中只有异步存储 API 可用。
扩展可以使用这些:

  • chrome.storage

    • 好:少量简单数据
    • 好:直接在内容脚本中可用
    • meh:只有与 JSON 兼容的类型(字符串、数字、布尔值、null、由这些类型递归组成的对象/数组),因此尝试存储复杂的东西,如 SetMap 将最终成为一个空对象{} 你必须序列化它们,例如写作时[...mySet],阅读时new Set(result.foo)
    • 不好:大/嵌套数据非常慢
  • IndexedDB

    • 好:对于任何数量/复杂性的数据都非常快
    • 很好:更多数据类型,如 ArrayBuffer、File、Blob、类型化数组、Set、Map、
      structured clone algorithm
    • meh:数据在内容脚本中不可用,因此您必须使用messaging
    • 不好:它的 API 已过时且笨拙,但有几个库可以修复它

这些 API 是异步的,因此您必须重新编写代码。
由于 Chrome 95 承诺 chrome.storage,我们可以使用 async/await 作为您的示例。
并且不要忘记在 manifest.json 中将 "storage" 添加到 "permissions"

const LS = chrome.storage.local;

async function pruneStorage() {
  const remover = Date.now() - 2500000000;
  const key = lastchecked[0];
  if ((await LS.get(key))[key] < remover) {
    await LS.set({[key]: Date.now()});
  } else {
    const toRemove = Object.entries(await LS.get())
      .map(([k, v]) => v < remover && k)
      .filter(Boolean);
    if (toRemove.length) {
      await LS.remove(toRemove);
    }
  }
}

或者,模仿localStorage

const LS = {
  getAllItems: () => chrome.storage.local.get(),
  getItem: async key => (await chrome.storage.local.get(key))[key],
  setItem: (key, val) => chrome.storage.local.set({[key]: val}),
  removeItems: keys => chrome.storage.local.remove(keys),
};

async function pruneStorage() {
  const remover = Date.now() - 2500000000;
  const key = lastchecked[0];
  if (await LS.getItem(key) < remover) {
    await LS.setItem(key, Date.now());
  } else {
    const toRemove = Object.entries(await LS.getAllItems())
      .map(([k, v]) => v < remover && k)
      .filter(Boolean);
    if (toRemove.length) {
      await LS.removeItems(toRemove);
    }
  }
}

警告:如果您想异步发送响应,请不要让您的 chrome.runtime.onMessage 侦听器 async,而是使用异步 IIFE 或单独的函数 more info

【讨论】:

    猜你喜欢
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    相关资源
    最近更新 更多