正在同步 sync 和本地 chrome.storage
Synchronizing sync and local chrome.storage
我想知道如何在 Chrome 扩展中以正确的方式处理本地和同步存储。
这是我的案例:
我正在为一个特定站点开发扩展(目前),
其中包含一个内容脚本和一个弹出窗口。
弹出窗口包含用户可以进行更改的选项,然后将值发送到内容脚本以在页面上显示更改。
我希望尽可能减少保存和检索存储任务,最终它将保存在同步存储中,而不仅仅是本地。
同步存储有每分钟限制,而本地没有。
我知道如何使用长期连接监听来自内容脚本的弹出关闭调用并监听 onConnect
和 onDisconnect
,然后我可以执行保存任务,但是有没有更好的方法来保存对存储的读写呢?
我能想到的就是有一个后台脚本,我可以在其中存储变量中的更改,然后将它们来回发送到内容脚本和弹出窗口,所以这就像有一个存储而不实际使用存储,但是然后我如何检测用户何时离开特定域然后执行单个保存任务,以及 close/stop background/event 脚本?
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 秒足以在页面关闭之前完成。
另外请注意,从该代码更新区域将再次触发该事件。这是 considered a bug(与 window.onstorage
相比,不触发当前文档中的更改),但同时我添加了 _syncStamp
属性。它用于区分本地回声,尽管有微小的机会导致碰撞
您的其他代码(内容脚本)也应该依赖于 onChanged
事件而不是自定义 "okay, I changed a value!" 消息。
我想知道如何在 Chrome 扩展中以正确的方式处理本地和同步存储。
这是我的案例:
我正在为一个特定站点开发扩展(目前),
其中包含一个内容脚本和一个弹出窗口。
弹出窗口包含用户可以进行更改的选项,然后将值发送到内容脚本以在页面上显示更改。
我希望尽可能减少保存和检索存储任务,最终它将保存在同步存储中,而不仅仅是本地。
同步存储有每分钟限制,而本地没有。
我知道如何使用长期连接监听来自内容脚本的弹出关闭调用并监听 onConnect
和 onDisconnect
,然后我可以执行保存任务,但是有没有更好的方法来保存对存储的读写呢?
我能想到的就是有一个后台脚本,我可以在其中存储变量中的更改,然后将它们来回发送到内容脚本和弹出窗口,所以这就像有一个存储而不实际使用存储,但是然后我如何检测用户何时离开特定域然后执行单个保存任务,以及 close/stop background/event 脚本?
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 秒足以在页面关闭之前完成。
另外请注意,从该代码更新区域将再次触发该事件。这是 considered a bug(与 window.onstorage
相比,不触发当前文档中的更改),但同时我添加了 _syncStamp
属性。它用于区分本地回声,尽管有微小的机会导致碰撞
您的其他代码(内容脚本)也应该依赖于 onChanged
事件而不是自定义 "okay, I changed a value!" 消息。