理解系列-localForage源码的降级策略
localForage 是什么
localForage 是一个 JavaScript 库,只需要通过简单类似 localStorage API 的异步存储来改进你的 Web 应用程序的离线体验。它能存储多种类型的数据,而不仅仅是字符串。
小知识:如果项目无需兼容 IE 浏览器,可以试试使用 yux-storage,代码 100 行左右,但可能兼容性不如localForage;
特点-降级缓存
数据储存回顾
- cookie 大小 4kb,任何 cookie 大小超过限制都被忽略,且永远不会被设置
- localStorage,虽然比 cookie 多,但是同样有上限(5M)左右
- websql 使用简单,存储量大,兼容性差
- indexDB api 多且繁琐,存储量大、高版本浏览器兼容性较好 >=250m
localForage 缓存
localForage 的出现就是采用降级缓存策略,进行缓存兼容,策略如下:
使用顺序:indexDB> websql>localStorage,localStorage是兜底的,因为兼容性几乎全覆盖:
localForage 包大小
未压缩30k左右(gzipped:9k左右),体积方面没啥问题
localForage 使用
// 通过 npm 安装:
npm install localForage
// 直接引用
<script src="localForage.js"></script>
<script>console.log('localForage is: ', localForage);</script>
//获取存储
localForage
.getItem('somekey')
.then(function (value) {})
.catch(function (err) {});
// 回调版本:
localForage.getItem('somekey', function (err, value) {});
//储存数据
localForage
.setItem('somekey', 'some value')
.then(function (value) {})
.catch(function (err) {});
// 不同于 localStorage,你可以存储非字符串类型
localForage
.setItem('my array', [1, 2, 'three'])
.then(function (value) {})
.catch(function (err) {});
//删除数据
localForage
.removeItem('somekey')
.then(function () {})
.catch(function (err) {});
localForage 源码-降级策略
为了统一缓存方法,三大类型缓存都暴露一致的api
var asyncStorage = {
_driver: 'asyncStorage',
_initStorage: _initStorage,
_support: isIndexedDBValid(),
iterate: iterate,
getItem: getItem,
setItem: setItem,
removeItem: removeItem,
clear: clear,
length: length,
key: key,
keys: keys,
dropInstance: dropInstance
};
var webSQLStorage = {
_driver: 'webSQLStorage',
_initStorage: _initStorage,
_support: isWebSQLValid(),
iterate: iterate,
getItem: getItem,
setItem: setItem,
removeItem: removeItem,
clear: clear,
length: length,
key: key,
keys: keys,
dropInstance: dropInstance
};
var localStorageWrapper = {
_driver: 'localStorageWrapper',
_initStorage: _initStorage,
_support: isLocalStorageValid(),
iterate: iterate,
getItem: getItem,
setItem: setItem,
removeItem: removeItem,
clear: clear,
length: length,
key: key,
keys: keys,
dropInstance: dropInstance
};
localForage类装载的api
const OptionalDriverMethods = ['dropInstance'];
const LibraryMethods = [
'clear',
'getItem',
'iterate',
'key',
'keys',
'length',
'removeItem',
'setItem'
].concat(OptionalDriverMethods);
降级策略
在初始化时候,localForage已经根据浏览器支持情况,按照优先使用 indexDB,其次是 websql,最后是 localStorage顺序设置好。
//在定义驱动数组的时候,已经默认好顺序
const DefaultDriverOrder = [
DefaultDrivers.INDEXEDDB._driver,
DefaultDrivers.WEBSQL._driver,
DefaultDrivers.LOCALSTORAGE._driver
];
//在设置驱动时候,已经通过
setDriver(drivers, callback, errorCallback) {
const supportedDrivers = this._getSupportedDrivers(drivers);
...省略无关代码
const oldDriverSetDone =
this._driverSet !== null
? this._driverSet.catch(() => Promise.resolve())
: Promise.resolve();
this._driverSet = oldDriverSetDone
.then(() => {
const driverName = supportedDrivers[0];//默认取驱动数组的第一个
self._dbInfo = null;
self._ready = null;
return self.getDriver(driverName).then(driver => {
self._driver = driver._driver;
setDriverToConfig();
self._wrapLibraryMethodsWithReady();
self._initDriver = initDriver(supportedDrivers);
});
})
.catch(() => {
setDriverToConfig();
const error = new Error('No available storage method found.');
self._driverSet = Promise.reject(error);
return self._driverSet;
});
}
//获取用户环境支持的驱动
_getSupportedDrivers(drivers) {
const supportedDrivers = [];
for (let i = 0, len = drivers.length; i < len; i++) {
const driverName = drivers[i];
if (this.supports(driverName)) {
supportedDrivers.push(driverName);
}
}
return supportedDrivers;
}
上面的初始化策略会有一个问题,如果用户切换环境,比如从支持 indexDB 的浏览器切换到不支持 indexDB 的浏览器,那么就会造成缓存不可用。
localforage.INDEXEDDB
localforage.WEBSQL
localforage.LOCALSTORAGE
//可以手动设置到对应的缓存驱动
localforage.setDriver(localforage.LOCALSTORAGE);
相关文档:
转载自:https://juejin.cn/post/7281830279447380005