如何在不覆盖其他写入操作的情况下将记录添加到 chrome.storage.local



我正在创建一个Chrome扩展程序来衡量某些类型的标签页活动。因此,我通过chrome.tabs创建了各种事件侦听器,这些侦听器可以侦听onReplacement,onUpdate,onCreated和其他事件。

这些侦听器中的每一个都需要存储数据,我正在使用存储API(chrome.storage.local(来做到这一点。但是,存储 API 基于回调,如其规范中所定义。

chrome.storage.local.get(key, myCallbackFunctionHere);

发生的情况是,我在各种事件侦听器中有多个对存储的调用,这些调用可能几乎同时触发。因此,您有两个不同的get调用存储 API,然后是存储一些数据的set调用。两组数据都需要存储,但它们相互覆盖,最终只存储了一组。

chrome.tabs.onCreated.addListener(onTabCreated);
chrome.tabs.onUpdated.addListener(onTabUpdated);
function onTabUpdated(tabId, changeInfo, tabAsUpdated) {
var someRelevantData = // extract some data to be stored 
chrome.storage.sync.get({'myKey' : {}}, function (data) { 
var myDictionaryUpdated = data.myKey;
myDictionaryUpdated ['newKey'] = someRelevantData;
chrome.storage.sync.set({'myKey' : myDictionaryUpdated }, function() { 
console.log("myKey updated --- new value is &s", JSON.stringify(myDictionaryUpdated, null, 4));
});
});
}
function onTabActivated(activeInfo) { 
var someDifferentAndEquallyImportantData = // extract some data to be stored 
chrome.storage.sync.get({'myKey' : {}}, function (data) { 
var myDictionaryUpdated = data.myKey;
myDictionaryUpdated['aSecondNewKey'] = someDifferentAndEquallyImportantData;
chrome.storage.sync.set({'myKey' : myDictionaryUpdated }, function() { 
console.log("myKey updated --- new value is &s", JSON.stringify(myDictionaryUpdated , null, 4));
});
});
}

onTabUpdate 的回调返回使用"myKey"存储的对象,然后添加到该对象并在存储中更新它。但是,onTabActivated 也会在"myKey"处获取对象(它仍然是空的,因为来自上一个回调的 set 调用尚未运行(,添加自己的数据,然后将更新的对象写入存储,覆盖包含在 onTabUpdated 回调中的任何数据。

我找不到有关存储 API 的良好文档或其他任何地方的答案 - 堆栈溢出的相关问题不涉及多个事件侦听器立即调用存储 API。

这是任何异步存储的标准问题,而不是特定于扩展。

解决方案 1.使用同步window.localStorage。它只能存储字符串,所以你需要JSON.stringify和JSON.parse来处理复杂数据。在性能方面,假设数据小于几千字节,则不会有任何区别,但如果有更多,则不要使用此方法。

解决方案 2.使用等待上一个调用完成的互斥读/写函数:

const storage = (() => {
let mutex = Promise.resolve();
const API = chrome.storage.sync;
const mutexExec = (method, data) => {
mutex = Promise.resolve(mutex)
.then(() => method(data))
.then(result => {
mutex = null;
return result;
});
return mutex;
};
const syncGet = data => new Promise(resolve => API.get(data, resolve));
const syncSet = data => new Promise(resolve => API.set(data, resolve));
return {
read: data => mutexExec(syncGet, data),
write: data => mutexExec(syncSet, data),
};
})();

用法:

async function example() {
const {myKey} = await storage.read({myKey: {}}); 
myKey.foo = 'bar';
await storage.write({myKey});
}

解决方案3:使用存储键值对的变量将缓存添加到以前的解决方案中,但这是读者的练习(周围可能有现有的库/示例(。

相关内容

最新更新