Javascript 同步和本地chrome.storage

Javascript 同步和本地chrome.storage,javascript,google-chrome-extension,Javascript,Google Chrome Extension,我想知道如何在Chrome extension中以正确的方式处理本地和同步存储 这就是我的情况: 我正在为一个特定的站点开发一个扩展(目前), 其中包含内容脚本和弹出窗口。 弹出窗口包含用户可以进行更改的选项,然后将值发送到内容脚本以在页面上显示更改 我希望尽可能少地保存和检索存储任务,最终它将保存在同步存储中,而不仅仅是本地存储。 同步存储有每分钟的限制,而本地存储没有 我知道如何使用长期连接从内容脚本收听弹出关闭调用,并收听onConnect和onDisconnect,然后我可以执行保存任务

我想知道如何在Chrome extension中以正确的方式处理本地和同步存储

这就是我的情况:
我正在为一个特定的站点开发一个扩展(目前),
其中包含内容脚本和弹出窗口。
弹出窗口包含用户可以进行更改的选项,然后将值发送到内容脚本以在页面上显示更改

我希望尽可能少地保存和检索存储任务,最终它将保存在同步存储中,而不仅仅是本地存储。
同步存储有每分钟的限制,而本地存储没有

我知道如何使用长期连接从内容脚本收听弹出关闭调用,并收听
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是每次安装的,所以在第一次读取后缓存它是有意义的。