2015-03-15 4 views
1

Я хотел бы знать, как правильно обращаться с локальным и синхронизирующим хранилищем в расширении Chrome.Синхронизация синхронизации и локального chrome.storage

Это мой случай:
Я работаю над расширением только для конкретного сайта (на данный момент),
, который содержит контент-скрипт, и всплывающее окно.
Всплывающее окно содержит параметры, в которых пользователь может вносить изменения, а затем значения передаются в контент-скрипт, чтобы отображать изменения на странице.

Я стараюсь как можно меньше экономить и извлекать задачи хранения, и в итоге он будет сохранен в хранилище синхронизации, а не только на локальном.
Хранилище синхронизации имеет ограничение в минуту, а местное - нет.

Я знаю, как слушать всплывающее закрытое сообщение из контент-скрипта с использованием долгоживущего соединения и слушать onConnect и onDisconnect, а затем я могу выполнить задачу сохранения, но есть лучший способ сохранить чтение и запись в хранилище?
Все, что я могу думать о том, что у меня есть фоновый скрипт, где я могу хранить изменения в переменных, а затем просто отправлять их обратно и пересылать и из контекстного скрипта и всплывающего окна, так что это похоже на хранение без фактического использования хранилища, но как я могу определить, когда пользователь покидает определенный домен, а затем выполняет одну задачу сохранения, а также закрывает/останавливает сценарий фона/события?

ответ

2

Действующий предел на chrome.storage.sync длительных операций составляет 1 раз в 2 секунды (точнее 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 случае вместо обычая «в порядке, Я изменил стоимость! " сообщение.

+0

Вы здоровы, спасибо! к сожалению, уже поздно, и я слишком устал прямо сейчас, чтобы читать и понимать, но обязательно обязательно вернусь к нему завтра и сообщит вам об этом :) –

+0

@GilGoldshlager Удивительно, как полно маленьких ловушек эта задача! Я все еще не работал в 100% случаев, но ~ 99.9999999% времени достаточно хорош. Я бы приветствовал конструктивную критику. – Xan

+0

Еще раз спасибо, я закончил тем, что просто сэкономил на всплывающем закрытии события (отсоединение порта), но он может использовать его в ближайшем будущем! –

Смежные вопросы