Javascript 同步和本地chrome.storage
我想知道如何在Chrome extension中以正确的方式处理本地和同步存储 这就是我的情况:Javascript 同步和本地chrome.storage,javascript,google-chrome-extension,Javascript,Google Chrome Extension,我想知道如何在Chrome extension中以正确的方式处理本地和同步存储 这就是我的情况: 我正在为一个特定的站点开发一个扩展(目前), 其中包含内容脚本和弹出窗口。 弹出窗口包含用户可以进行更改的选项,然后将值发送到内容脚本以在页面上显示更改 我希望尽可能少地保存和检索存储任务,最终它将保存在同步存储中,而不仅仅是本地存储。 同步存储有每分钟的限制,而本地存储没有 我知道如何使用长期连接从内容脚本收听弹出关闭调用,并收听onConnect和onDisconnect,然后我可以执行保存任务
我正在为一个特定的站点开发一个扩展(目前),
其中包含内容脚本和弹出窗口。
弹出窗口包含用户可以进行更改的选项,然后将值发送到内容脚本以在页面上显示更改 我希望尽可能少地保存和检索存储任务,最终它将保存在同步存储中,而不仅仅是本地存储。
同步存储有每分钟的限制,而本地存储没有 我知道如何使用长期连接从内容脚本收听弹出关闭调用,并收听
onConnect
和onDisconnect
,然后我可以执行保存任务,但有没有更好的方法将读写保存到存储器中?我所能想到的就是有一个后台脚本,我可以在其中存储变量中的更改,然后将它们发送回内容脚本和弹出窗口,这样就好像有一个没有实际使用存储的存储,但是我如何检测用户何时离开特定域,然后执行单个保存任务,同时关闭/停止后台/事件脚本?chrome.storage.sync持续操作的当前限制为每2秒1次(更准确地说是每小时1800次),突发速率限制为每分钟120次 因此,您的工作是确保同步频率不超过每2秒一次 我会制作一个事件页面,处理
chrome.storage.onChanged
事件并同步这两个区域由于本地回声,这是一项异常困难的任务强>
// event.js, goes into background.scripts in manifest
// Those will not persist if event page is unloaded
var timeout;
var queuedChanges = {};
var syncStamp = 1;
chrome.storage.onChanged.addListener(function(changes, area) {
// Check if it's an echo of our changes
if(changes._syncStamp && changes._syncStamp.newValue == syncStamp) {
return;
}
if(area == "local") {
// Change in local storage: queue a flush to sync
// Reset timeout
if(timeout) { clearTimeout(timeout); }
// Merge changes with already queued ones
for(var key in changes) {
// Just overwrite old change; we don't care about last newValue
queuedChanges[key] = changes[key];
}
// Schedule flush
timeout = setTimeout(flushToSync, 3000);
} else {
// Change in sync storage: copy to local
if(changes._syncStamp && changes._syncStamp.newValue) {
// Ignore those changes when they echo as local
syncStamp = changes._syncStamp.newValue;
}
commitChanges(changes, chrome.storage.local);
}
});
function flushToSync() {
// Be mindful of what gets synced: there are also size quotas
// If needed, filter queuedChanges here
// Generate a new sync stamp
// With random instead of sequential, there's a really tiny chance
// changes will be ignored, but no chance of stamp overflow
syncStamp = Math.random();
queuedChanges._syncStamp = {newValue: syncStamp};
// Process queue for committing
commitChanges(queuedChanges, chrome.storage.sync);
// Reset queue
queuedChanges = {};
timeout = undefined;
}
function commitChanges(changes, storage) {
var setData = {};
for(var key in changes) {
setData[key] = changes[key].newValue;
}
storage.set(setData, function() {
if(chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
}
});
}
这里的想法是在最后一次更改为local
后同步3秒。每个新的更改都会添加到队列中并重置倒计时。虽然Chrome通常不支持事件页面中的DOM计时器,但在页面关闭之前,3秒钟足够短
另外,请注意,根据此代码更新区域将再次触发事件。这是(与window.onstorage
相比,当前文档中的更改不会触发),但同时我添加了\u syncStamp
属性。它被用来区分局部回波,尽管有一个微小的机会,邮票将导致碰撞
您的其他代码(内容脚本)可能也应该依赖于
onChanged
事件,而不是自定义的“好的,我更改了值!”消息。您太棒了,谢谢!不幸的是,现在已经很晚了,我现在太累了,无法阅读、理解和尝试它,但明天肯定会回来,并会让你知道:)@GilGoldshlager这项任务充满了小陷阱,真令人惊讶!我仍然没有让它100%的时间工作,但是99.9999999%的时间已经足够了。不过,我欢迎建设性的批评。再次感谢,我最后只保存了弹出关闭事件(端口断开连接),但您可能会在不久的将来使用它!至于戳记冲突,我认为在安装时创建一些自定义ID更安全,将该ID附加到每个storage.sync.set
(作为obj属性),当storage.onChanged
侦听器启动时,比较ID(ID保存在本地存储中)。我确实需要在每次比较时从存储中加载ID,但这非常简单forward@WolfWar因为ID是每次安装的,所以在第一次读取后缓存它是有意义的。