最近接手了一个新项目,打开一个文件时,我看到了一行让我一头雾水的代码:
localStorage.get().then(...)
“这tm谁写的代码?”我心里想着,localStorage
不是同步的吗?怎么会有 .then()
这样的用法?我忍不住找旁边的同事吐槽了一番。
同事笑着说:“仔细看一下。”
瞬间,我意识到我的尴尬:这并不是 localStorage
,而是 localForage
!这俩单词也太像了吧!我不禁会心一笑,心里暗想,看来我得好好了解一下这个库。
什么是 LocalForage?
LocalForage 是一个用于在浏览器中存储数据的 JavaScript 库,旨在提供类似于本地存储的 API,但支持更多的数据类型和更大的存储空间。目的是简化在 Web 应用中使用异步存储的过程。
在很多 Web 应用中,开发者需要在用户的浏览器中存储数据,比如用户设置、游戏进度或者离线数据等。传统的 localStorage
和 sessionStorage
只支持字符串存储,而且存储空间有限。LocalForage 通过封装 IndexedDB、WebSQL 和 localStorage,使得开发者可以使用简单的 API 来处理不同类型的数据(如对象和数组),并且异步操作不会阻塞主线程。
使用方式
-
安装
可以通过 npm 安装 LocalForage:
npm install localforage
或者直接在 HTML 文件中引入:
<script src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js"></script>
-
基本用法
LocalForage 提供了一系列简单的方法来存储、获取和删除数据。
-
设置数据
localforage.setItem('key', { name: 'Alice', age: 25 }) .then(function () { console.log('Data saved successfully!'); }) .catch(function (err) { console.error('Error saving data:', err); });
-
获取数据
localforage.getItem('key') .then(function (value) { console.log('Retrieved data:', value); }) .catch(function (err) { console.error('Error retrieving data:', err); });
-
删除数据
localforage.removeItem('key') .then(function () { console.log('Data removed successfully!'); }) .catch(function (err) { console.error('Error removing data:', err); });
-
清空数据
localforage.clear() .then(function () { console.log('All data cleared!'); }) .catch(function (err) { console.error('Error clearing data:', err); });
-
配置选项
LocalForage 允许开发者在初始化时进行配置,例如设置数据库名称、版本等:
localforage.config({ driver: localforage.INDEXEDDB, // 使用的存储驱动 name: 'myApp', version: 1.0, storeName: 'keyvaluepairs', // 存储的表名 description: 'Some description' });
-
源码解读
目录
三个driver
三个driver都会导出如下对象,然后在LocalForage类中使用
constructor中setDriver
LocalForage类中会设置setDriver,在其中初始化一些参数
self._driver = driver._driver;
setDriverToConfig();
self._wrapLibraryMethodsWithReady();
self._initDriver = initDriver(supportedDrivers);
ready之后执行self._initDriver()
ready(callback) {
const self = this;
const promise = self._driverSet.then(() => {
if (self._ready === null) {
self._ready = self._initDriver();
}
return self._ready;
});
executeTwoCallbacks(promise, callback, callback);
return promise;
}
_initDriver中执行extendSelfWithDriver扩展对象方法
extendSelfWithDriver之后就会有getItem等方法了
function extendSelfWithDriver(driver) {
self._extend(driver);
setDriverToConfig();
self._ready = self._initStorage(self._config);
return self._ready;
}
以封装getItem为例子
以localStorage中为例
this就是new LocalForage(),会等ready之后执行对应的localStorage.getItem操作,然后返回promise
function getItem(key, callback) {
var self = this;
key = normalizeKey(key);
var promise = self.ready().then(function() {
var dbInfo = self._dbInfo;
var result = localStorage.getItem(dbInfo.keyPrefix + key);
// If a result was found, parse it from the serialized
// string into a JS object. If result isn't truthy, the key
// is likely undefined and we'll pass it straight to the
// callback.
if (result) {
result = dbInfo.serializer.deserialize(result);
}
return result;
});
executeCallback(promise, callback);
return promise;
}