此问题的解决方案是创建您自己的存储API。您已经确定localStorage是同步的,而Chrome存储是异步的,但这只是简单地将所有内容视为异步而轻易解决的问题。
创建您自己的API,然后用它代替所有其他调用。代码中的快速查找/替换可以用新API替换localStorage调用。
function LocalStorageAsync() {
/**
* Parses a boolean from a string, or the boolean if an actual boolean argument is passed in.
*
* @param {String|Boolean} bool A string representation of a boolean value
* @return {Boolean} Returns a boolean value, if the string can be parsed as a bool.
*/
function parseBool(bool) {
if (typeof bool !== 'string' && typeof bool !== 'boolean')
throw new Error('bool is not of type boolean or string');
if (typeof bool == 'boolean') return bool;
return bool === 'true' ? true : false;
}
/**
* store the key value pair and fire the callback function.
*/
this.setItem = function(key, value, callback) {
if(chrome && chrome.storage) {
chrome.storage.local.set({key: key, value: value}, callback);
} else {
var type = typeof value;
var serializedValue = value;
if(type === 'object') {
serializedValue = JSON.stringify(value);
}
value = type + '::typeOf::' + serializedValue;
window.localStorage.setItem(key, value);
callback();
}
}
/**
* Get the item from storage and fire the callback.
*/
this.getItem = function(key, callback) {
if(chrome && chrome.storage) {
chrome.storage.local.get(key, callback);
} else {
var stronglyTypedValue = window.localStorage.getItem(key);
var type = stronglyTypedValue.split('::typeOf::')[0];
var valueAsString = stronglyTypedValue.split('::typeOf::')[1];
var value;
if(type === 'object') {
value = JSON.parse(valueAsString);
} else if(type === 'boolean') {
value = parseBool(valueAsString);
} else if(type === 'number') {
value = parseFloat(valueAsString);
} else if(type === 'string') {
value = valueAsString;
}
callback(value);
}
}
}
// usage example
l = new LocalStorageAsync();
l.setItem('test',[1,2,3], function() {console.log('test');});
l.getItem('test', function(e) { console.log(e);});
的一个问题下面这个解决方案克服了,除了处理一切为异步的,是它也解释了所有的localStorage一切转换为字符串的事实。通过将类型信息保存为元数据,我们确保getItem操作产生的内容与进入的数据类型相同。
更重要的是,使用工厂模式的变体,您可以创建两个具体的内部子类并根据环境返回相应的代码:
function LocalStorageAsync() {
var private = {};
private.LocalStorage = function() {
function parseBool(bool) {
if (typeof bool !== 'string' && typeof bool !== 'boolean')
throw new Error('bool is not of type boolean or string');
if (typeof bool == 'boolean') return bool;
return bool === 'true' ? true : false;
}
this.setItem = function(key, value, callback) { /* localStorage impl... */ };
this.getItem = function(key, callback) { /* ... */ };
};
private.ChromeStorage = function() {
this.setItem = function(key, value, callback) { /* chrome.storage impl... */ };
this.getItem = function(key, callback) { /* ... */ };
}
if(chrome && chrome.storage)
return new private.ChromeStorage();
else
return new private.LocalStorage();
};
谢谢!这种方法对我来说很有意义。将这些函数拆分成类似localStorageSetItem()/ localStorageGetItem()和chromeStorageSetItem()/ chromeStorageGetItem()的东西是否是一个好主意,然后在页面加载时创建一个存储对象来决定使用哪一个? – 2014-10-08 05:39:08
@BenjaminHumphrey - 是的,除了我会使用类似工厂模式的东西,而是确保两个子类的接口都是相同的API和方法签名。然后构造函数或工厂方法可以处理返回适当的实现。我更新了这篇文章,举例说明了我过去如何处理这个问题。用法与上例相同,但实现更独立且独立。伟大的问题! – jmort253 2014-10-08 15:05:25