如何在 Manifest v3 中使用 localStorage 或替代方案
How to use localStorage or an alternative in Manifest v3
我正在尝试将 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
之外,是否有任何简单的方法可以将其切换为使用其他东西,因为它不可用?
根据规范,localStorage
在 service worker 中不可用。原因是因为它提供同步访问,所以在启动 JS 环境之前必须完整读取它,这可能需要一些时间,这与环境本身的启动时间(~50ms)相当,以防存储包含几兆字节(最大为 5MB)。
Service Worker 中只有异步存储 API 可用。
扩展可以使用这些:
-
- 好:数据量小
- 好:直接在内容脚本中可用
- meh:只有 JSON 兼容的类型(字符串、数字、布尔值、null,object/array 由这些类型递归组成),因此试图存储复杂的东西,如
Set
或Map
将以空对象 {}
结束,您必须 序列化 它们,例如写入时[...mySet]
,读取时new Set(result.foo)
。
- 不好:big/nested 数据非常慢
-
- 好:对于任何 amount/complexity 数据都非常快
- 好:更多数据类型,如 ArrayBuffer、File、Blob、类型化数组、Set、Map,
查看 structured clone algorithm
- meh:数据在内容脚本中不可用,因此您必须使用 messaging
- 不好:它的 API 已经过时且笨拙,但是有几个库可以修复它
这些 API 是异步的,因此您将不得不重新编写代码。
由于 Chrome 95 promified 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 或单独的函数,。
我正在尝试将 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
之外,是否有任何简单的方法可以将其切换为使用其他东西,因为它不可用?
localStorage
在 service worker 中不可用。原因是因为它提供同步访问,所以在启动 JS 环境之前必须完整读取它,这可能需要一些时间,这与环境本身的启动时间(~50ms)相当,以防存储包含几兆字节(最大为 5MB)。
Service Worker 中只有异步存储 API 可用。
扩展可以使用这些:
-
- 好:数据量小
- 好:直接在内容脚本中可用
- meh:只有 JSON 兼容的类型(字符串、数字、布尔值、null,object/array 由这些类型递归组成),因此试图存储复杂的东西,如
Set
或Map
将以空对象{}
结束,您必须 序列化 它们,例如写入时[...mySet]
,读取时new Set(result.foo)
。 - 不好:big/nested 数据非常慢
-
- 好:对于任何 amount/complexity 数据都非常快
- 好:更多数据类型,如 ArrayBuffer、File、Blob、类型化数组、Set、Map,
查看 structured clone algorithm - meh:数据在内容脚本中不可用,因此您必须使用 messaging
- 不好:它的 API 已经过时且笨拙,但是有几个库可以修复它
这些 API 是异步的,因此您将不得不重新编写代码。
由于 Chrome 95 promified 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 或单独的函数,