
前端缓存抽象【免费下载链接】localForage Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.项目地址https://gitcode.com/gh_mirrors/lo/localForage点击查看免费下载localForage 是一个面向 JavaScript 的快速、简洁的离线存储库它用一套与localStorage高度一致的简单 API 封装了 IndexedDB、WebSQL 与 localStorage 三种浏览器存储后端并自动完成异步化与驱动回退。本文以本仓库 README.md 为主体结合 src/localforage.js 及各驱动源码完整讲解安装方式、双 API 用法、配置项语义、多实例、自定义驱动与本地开发测试帮助你在真实项目中安全落地离线数据存储。什么是 localForagelocalForage 的核心设计目标可以用一句话概括用异步存储IndexedDB 或 WebSQL配合简单、localStorage风格的 API改善 Web 应用的离线体验。它解决了原生浏览器存储的三大痛点localStorage是同步 API在主线程上做字符串序列化会阻塞 UIlocalStorage容量有限通常 5MB 左右且只能存字符串IndexedDB / WebSQL 虽然强大但原生 API 冗长、回调繁琐学习与使用成本高。localForage 在支持 IndexedDB 或 WebSQL 的浏览器中优先使用异步后端在没有二者的浏览器或隐私模式下两者被禁用中自动回退到 localStorage从而在不同环境下提供一致的编程体验。仓库 package.json 显示当前版本为1.10.0由 Mozilla 维护采用 Apache-2.0 许可唯一的运行时依赖是 Promise polyfill 库lie见 src/utils/promise.js当全局Promise不存在时自动加载lie/polyfill。安装与快速开始通过 script 标签引入localForage 设计为丢一个 JS 文件进页面即可用。引入构建产物后全局会暴露localforage对象script srclocalforage/dist/localforage.js/script scriptlocalforage.getItem(something, myCallback);/script仓库根目录的dist构建产物由 Grunt 任务生成见 Gruntfile.js 与 package.json 中的build脚本源码位于 src/localforage.js入口默认导出的是一个已经初始化好的单例new LocalForage()。通过 npm 安装npm install localforage安装后在支持 ES Module / CommonJS 的构建工具中直接import localforage from localforage即可使用。最小示例// 写 localforage.setItem(key, value); // 读 localforage.getItem(key).then(function (value) { console.log(value); });核心 APICallback 与 Promise 双形态因为 localForage 走的是异步存储所以它的 API 天然是异步的除此之外调用方式与localStorageAPI 几乎一一对应getItem/setItem/removeItem/clear/key/keys/length。它同时提供 Node 风格回调与 Promise 两种形态官方建议优先使用 Promise。Node 风格回调localforage.setItem(key, value, function (err) { // 如果 err 非 null说明出错了 localforage.getItem(key, function (err, value) { // 如果 err 非 null说明出错了否则 value 就是取到的值 }); });注意回调签名的统一约定错误永远在第一个参数成功数据在第二个参数。Promise 链式写法localforage.setItem(key, value).then(function () { return localforage.getItem(key); }).then(function (value) { // 这里拿到 value }).catch(function (err) { // 出错处理 });async/await 写法try { const value await localforage.getItem(somekey); // 值从离线存储中加载完成后此代码才会执行 console.log(value); } catch (err) { // 出错处理 console.log(err); }从源码结构看这套双 API是由 src/utils/executeCallback.js 与 src/utils/executeTwoCallbacks.js 实现的每个驱动方法内部先构造 Promise再通过这两个工具把可选的回调接入 Promise 的成功/失败路径从而让同一份实现同时支持回调和 Promise 两种调用方式。完整的 API 清单除读写外localForage 还提供以下方法全部支持回调与 Promise 双形态方法说明getItem(key)读取键对应的值不存在时返回nullsetItem(key, value)写入键值resolve 时返回被写入的值removeItem(key)删除一个键clear()清空当前实例的所有数据length()返回当前 store 中键的数量key(n)返回第 n 个键IndexedDB 下用游标advance(n)实现见 src/drivers/indexeddb.jskeys()返回所有键的数组iterate(iterator)遍历所有键值迭代器返回非undefined值时立即终止遍历dropInstance(options)按数据库名/存储名删除整个实例可选方法见下文自定义驱动一节可以存储任意类型Blob、TypedArray 与普通 JS 对象与只能存字符串的localStorage不同localForage 可以存储任意类型所有能被 JSON 序列化的原生 JS 对象以及 ArrayBuffer、Blob、TypedArray。即使底层后端是 localStoragelocalForage 也会在读写时自动执行JSON.stringify()/JSON.parse()所以这些类型依然可用——唯一的限制是 localStorage 的容量约束决定了它装不下太多大 Blob。这一能力在 IndexedDB 后端由 src/drivers/indexeddb.js 原生支持在 WebSQL / localStorage 后端则由 src/utils/serializer.js 实现。序列化器的工作原理非常值得了解普通对象走JSON.stringify/JSON.parseArrayBuffer 与各 TypedArrayInt8Array、Uint8Array、Uint8ClampedArray、Int16Array、Uint16Array、Int32Array、Uint32Array、Float32Array、Float64Array会被转换为 Base64 字符串并加上__lfsc__:前缀与类型标记如arbf、ui08、fl32Blob 会被FileReader读出为 ArrayBuffer 后同样转成带blob类型标记的字符串type信息通过~~local_forage_type~前缀保留反序列化时依据标记还原出原始类型见 serializer.js 中的deserialize。而在 IndexedDB 后端当浏览器不支持原生 Blob 存储如 Chrome 43详见 indexeddb.js 中的_checkBlobSupport与_encodeBlob时驱动会先把 Blob 编码为带__local_forage_encoded_blob标记的对象再入库读取时解码还原保证跨浏览器行为一致。配置详解config() 的六个选项通过config()方法可以设置数据库信息可用选项为driver、name、storeName、version、size、description。完整示例与 README 一致localforage.config({ driver : localforage.WEBSQL, // 强制使用 WebSQL等价于调用 setDriver() name : myApp, version : 1.0, size : 4980736, // 数据库大小单位字节。目前仅 WebSQL 生效。 storeName : keyvaluepairs, // 应为字母数字可带下划线 description : some description });各选项的语义与实现细节结合 src/localforage.js 的DefaultConfig与config()方法选项默认值说明driver[asyncStorage, webSQLStorage, localStorageWrapper]按序回退可传字符串或字符串数组见下文驱动选择与回退一节namelocalforage数据库名IndexedDB/WebSQL 中对应真实数据库名localStorage 后端中作为键前缀的一部分storeNamekeyvaluepairs存储区名对应 IndexedDB 的 object store、WebSQL 的数据表localStorage 后端中拼入键前缀。源码会对该值做清洗options[i].replace(/\W/g, _)即把非字母数字字符统一替换为下划线version1.0数据库版本号。源码强制校验typeof options[i] ! number时直接返回Error(Database version must be a number.)size4980736数据库大小字节。默认值刻意设为略低于 5MB因为这是无需弹窗即可使用的最大配额。注释明确说明WebSQL-only for nowdescription数据库描述仅作元信息使用 config() 的三个关键注意点必须在读写之前调用README 明确强调必须在调用getItem()、setItem()、removeItem()、clear()、key()、keys()、length()等任何数据操作之前调用config()。源码也印证了这一点——config()内部会检查this._ready如果实例已经就绪会直接返回错误Cant call config() after localforage has been used.。config()兼具 getter 功能传入字符串时返回对应配置值config(name)不传参数时返回整个配置对象。传入driver时配置完成后会自动触发setDriver(this._config.driver)等价于手动调用setDriver()。多实例createInstance不同业务模块可能需要互相隔离的存储区。createInstance可以创建指向不同 store 的多个 localForage 实例config()支持的全部选项它都支持var store localforage.createInstance({ name: nameHere }); var otherStore localforage.createInstance({ name: otherName }); // 在一个实例上写 key不影响另一个实例 store.setItem(key, value); otherStore.setItem(key, value2);从源码看createInstance(options)就是return new LocalForage(options)见 src/localforage.js每个实例拥有独立的_config、_dbInfo与驱动状态。有意思的是IndexedDB 驱动内部通过dbContexts按数据库名维护共享上下文见 src/drivers/indexeddb.js 的createDbContext同一数据库名下的多个实例会共享同一个数据库连接并通过_deferReadiness/_advanceReadiness把每个实例的ready()串成一条就绪链避免并发打开/升级数据库时的竞争条件同时每个实例用不同的storeName即可实现互不干扰的逻辑隔离。这也解释了为什么多个实例指向同一数据库时实例间的初始化会相互等待。驱动选择与自动回退机制localForage 内置三个驱动见 src/localforage.js 的DefaultDrivers默认按以下顺序尝试IndexedDBasyncStoragesrc/drivers/indexeddb.js——容量大、支持任意类型、异步是首选WebSQLwebSQLStoragesrc/drivers/websql.js——基于 SQLite 的异步存储localStoragelocalStorageWrappersrc/drivers/localstorage.js——最后的兜底方案。驱动可用性由各自的_support检测函数决定并缓存在DriverSupport中localforage.supports(driverName)可查询IndexedDB见 src/utils/isIndexedDBValid.js。它做了非常细致的检测——排除被伪装成 Safari 的 IE Mobile对 Safari 要求同时存在原生fetch用于排除 Safari 10.1 对 IDB 支持不达标的情况要求存在indexedDB与IDBKeyRange后者用于排除三星、HTC 等 Android 4.4 设备的残缺实现WebSQL见 src/utils/isWebSQLValid.js仅判断typeof openDatabase functionlocalStorage见 src/utils/isLocalStorageValid.js。回退逻辑实现在setDriver()中src/localforage.js先通过_getSupportedDrivers()过滤出当前环境支持的驱动再在initDriver的driverPromiseLoop中逐个尝试——前一个驱动初始化失败就 catch 后尝试下一个全部失败则 reject 并抛出No available storage method found.。因此你也可以手动指定驱动顺序例如// 只尝试 IndexedDB 与 localStorage localforage.setDriver([localforage.INDEXEDDB, localforage.LOCALSTORAGE]);localStorage 后端还有一层额外防护初始化时通过checkIfLocalStorageThrows()实际写入一个测试键来探测存储是否可用并专门处理了 Safari 隐私模式下配额为 0 的情况见 localstorage.js 的_isLocalStorageUsable写入时捕获QuotaExceededError/NS_ERROR_DOM_QUOTA_REACHED并作为 Promise 拒绝抛出。localStorage 后端的键以name/与非默认时storeName/作为前缀_getKeyPrefix从而与页面中其他直接使用 localStorage 的代码隔离。与 RequireJS / 模块化工具搭配使用localForage 以 UMD 形式发布可直接与 RequireJS 配合define([localforage], function(localforage) { // 回调形式 localforage.setItem(mykey, myvalue, console.log); // Promise 形式 localforage.setItem(mykey, myvalue).then(console.log); });仓库 examples/require.html 与 examples/require.js 提供了可运行的 RequireJS 示例。TypeScript 类型支持仓库自带类型声明 typings/localforage.d.tspackage.json的typings字段指向它其中定义了LocalForageOptionsdriver、name、storeName、size、version、description与config()完全对应、LocalForageDbMethodsCoregetItem、setItem、removeItem、clear、length、key、keys、iterate的泛型签名以及自定义驱动接口LocalForageDriver。typing-tests/localforage-tests.ts中还有针对这些类型的编译期测试。导入方式取决于 tsconfig 配置若开启了allowSyntheticDefaultImportsTypeScript 1.8 支持推荐import localForage from localforage;否则使用以下两种之一import * as localForage from localforage; // 或者当你的 TypeScript 版本不支持对 UMD 模块使用 ES6 风格导入时 import localForage require(localforage);自定义驱动defineDriver如果你需要接入新的存储后端比如 Cordova 插件或其他第三方存储localForage 提供了defineDriver()注册机制。注册后的驱动对所有 localForage 实例全局共享源码中的DefinedDrivers容器。自定义驱动需要实现一组方法包括_initStorage与核心数据方法getItem、setItem、removeItem、clear、length、key、keys、iterate以及可选的dropInstance并且要提供_driver名称与_support支持检测。defineDriver内部src/localforage.js会对驱动做合规校验_driver必须存在且不与内置驱动重名必需方法缺失或不是函数时拒绝注册并抛出Custom driver not compliant; see ...#definedriver错误可选方法如dropInstance未实现时会自动注入一个抛错Method ... is not implemented by the current driver的占位实现_support既可以是布尔值也可以是返回 Promise 的异步检测函数。测试目录中的 test/dummyStorageDriver.js 就是一个可直接参考的哑驱动实现配合 test.customdriver.js 可以学习驱动注册与使用的最小完整流程。仓库还内置了dropInstance的完整实现示例见 examples/dropInstance.html。框架生态社区为多个框架提供了基于 localForage 的存储适配层可以让框架的模型/状态直接落地到离线存储AngularJSangular-localForage、Angular 4ngforage、BackbonelocalForage-backbone、Emberember-localforage-adapter、Vuevlf以及 NuxtJSlocalforage-module。如需将自己的驱动加入该列表可以在仓库 issues 中提交。本地开发与测试本地开发需要 node/npm 与 bower。准备工作# 全局安装 bower如未安装 npm install -g bower # 克隆并安装依赖 git clone gitgithub.com:USERNAME/localForage.git cd localForage npm install bower install注意省略 bower 依赖会导致测试失败因为 localForage 面向浏览器设计测试用例显式依赖浏览器环境。运行测试npm test # 或直接运行 grunt test本地测试运行在无头 WebKitPhantomJS上因此需要先安装 PhantomJS代码同时必须通过 linterjshint检查。提交 Pull Request 时CITravis Sauce Labs会对 localForage 支持的所有浏览器跑一遍测试矩阵。仓库的测试体系覆盖了核心 APItest/test.api.js其中包含iterate、dropInstance等方法的用例、数据类型test/test.datatypes.js、驱动选择test/test.drivers.js、配置test/test.config.js、多实例、Service Workers 与 Web Workerstest/test.serviceworkers.js、test/test.webworkers.js等场景。体积与许可从 1.7.3 版本起localForage 的打包体积非常可控使用 gzip 压缩后为应用增加不到 10KB 的负载形态体积minified~29kBgzipped~8.8kBbrotli~7.8kBlocalForage 以 Apache License 2.0 协议分发见仓库 LICENSE版权归 Mozilla2013-2016及其贡献者所有。若你的项目需要离线优先、跨后端一致的键值存储方案localForage 提供的这套简单 API 自动回退 任意类型支持的组合是值得优先评估的落地方案。赞分享前端缓存抽象【免费下载链接】localForage Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.项目地址https://gitcode.com/gh_mirrors/lo/localForage点击查看免费下载相关推荐localForage API 完全指南用一套 Promise 风格 API 打通 IndexedDB、WebSQL 与 localStoragelocalForage API 完全指南用一套 Promise 风格 API 打通 IndexedDB、WebSQL 与 localStorage local前端缓存抽象7-Zip-zstd实战指南现代压缩算法的终极解决方案7 Zip zstd实战指南现代压缩算法的终极解决方案 你是否还在为传统压缩工具的缓慢速度而烦恼7 Zip zstd正是为你量身定制的解决方案这个强大的开桌面应用CLIlocalForage与localStorage异步存储的终极对比指南localForage与localStorage异步存储的终极对比指南 localForage是一款快速简单的JavaScript存储库通过使用异步存储I前端缓存抽象上一篇450终端配色方案3步生效iTerm2-Color-Schemes 实用指南下一篇AionUi 如何在 Android Termux 中用 Proot Ubuntu 运行 WebUI 模式并实现局域网远程访问创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考