我想知道如何在Chrome扩展程序中以正确的方式处理本地存储和同步存储。
这是我的情况:
我正在为一个特定的网站(现在)进行扩展工作,
其中包含内容脚本和弹出窗口
弹出窗口包含用户可以进行更改的选项,然后将值发送到内容脚本以显示页面上的更改。
我希望减少保存并尽可能少地检索存储任务,最终它将保存在同步存储中,而不仅仅保存在本地存储中。
同步存储达到了每分钟限制,而本地存储没有限制。
我知道如何使用长期连接从内容脚本中听取弹出窗口关闭调用并听取onConnect
和onDisconnect
,然后我可以执行保存任务,但是是否有更好的方法来保存读取和写入存储?
我能想到的只有一个后台脚本,我可以将更改存储在变量中,然后只需将它们往返于内容脚本和弹出窗口,然后将其发送到内部脚本和弹出窗口,这就像拥有存储而不实际使用存储,但是如何检测用户何时离开特定域然后执行单个保存任务,还关闭/停止后台/事件脚本?
答案 0 :(得分:2)
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);
}
});
}
这里的想法是在最后一次更改后3秒钟同步到local
。每个新更改都会添加到队列中并重置倒计时。虽然Chrome通常不会在事件页面中使用DOM计时器,但在页面关闭之前3秒就足够短了。
另请注意,从此代码更新区域将再次触发事件。这是considered a bug(与window.onstorage
相比,当前文档中的更改没有触发),但同时我添加了_syncStamp
属性。它用于区分本地回声,但有一个很小的可能性,这个图章会导致碰撞
你的其他代码(内容脚本)应该也可能依赖于onChanged
事件而不是自定义“好吧,我改了一个值!”消息。