同步同步和本地chrome.storage

时间:2015-03-15 15:50:00

标签: javascript google-chrome-extension

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

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

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

我知道如何使用长期连接从内容脚本中听取弹出窗口关闭调用并听取onConnectonDisconnect,然后我可以执行保存任务,但是是否有更好的方法来保存读取和写入存储? 我能想到的只有一个后台脚本,我可以将更改存储在变量中,然后只需将它们往返于内容脚本和弹出窗口,然后将其发送到内部脚本和弹出窗口,这就像拥有存储而不实际使用存储,但是如何检测用户何时离开特定域然后执行单个保存任务,还关闭/停止后台/事件脚本?

1 个答案:

答案 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事件而不是自定义“好吧,我改了一个值!”消息。