当前位置: 首页 > 科技观察

说说前端仓库Localforage和存储配额

时间:2023-03-23 11:05:18 科技观察

前言浏览器本地存储是每个前端小伙伴都比较熟悉的一个知识点。目前使用最多的是WebStorageAPI,即localStorage和sessionStorage。API简单,读取效率高。然后是indexedDB,但更多时候存在于八股论文和面试题中。indexedDB的优点是存储空间大,支持多种数据结构,性能上没有问题。它没有被重用的原因是因为indexedDB有很多很长很复杂的API。另外,前端使用数据库,需要了解一些表、游标、事务等概念。对于不懂后端的同学来说,上手成本远高于localStorage。所以在5M以内的存储领域,indexedDB并不是首选。另外,WebSQL已经被H5标准抛弃,老牌的cookie已经不适合现代客户端的存储任务。那么有没有一种既能轻松上手又能保留indexedDB优点的方法呢?答案就是封装js库,localforage是比较成熟的方案。localforage简介localforage是一个JavaScript库,它通过类似于localStorageAPI的简单异步存储来改善Web应用程序的离线体验。它可以存储多种类型的数据,而不仅仅是字符串。localforage采用优雅的降级策略。如果浏览器不支持indexedDB或WebSQL,请使用localStorage。因此,在首选indexedDB存储的前提下,兼容性也得到保证,可以在各大主流浏览器中使用:Chrome、Firefox、IE和Safari(包括SafariMobile)。localforage在github上有21.5kstar,npm下载量每周200万左右,正常使用不会有问题。使用方法详细的使用方法不再过多描述,仅以访问示例为例。setItem//通过localForage完成存储localforage.setItem('key','value').then(doSomethingElse);//localForage也支持回调函数localforage.setItem('key','value',doSomethingElse);getItemlocalforage.getItem('somekey').then(function(value){//当加载离线仓库中的值时,这里的代码运行console.log(value);}).catch(function(err){//当出错时,这段代码运行console.log(err);});//Callbackversion:localforage.getItem('somekey',function(err,value){//当加载离线仓库中的值时,这里代码运行console.log(value);});实践在一次业务需求中,基于以下两点,果断选择了localforage。后面会有大量的数据需要存储在本地。转转里面有一个基于localforage.js二次封装的库,里面有设置过期时间的方法,适合这个需求。上线后的一段时间,功能运行的很流畅。直到sentry(错误日志监控系统)出现大量关于内存溢出的错误……问题很难重现。一开始怀疑是localforage存在兼容性问题,但是localforage有优雅的降级机制。另外报错内容是QuotaExceededError,所以看了很多资料,基本锁定是indexedDB的使用有问题。另外,报错用户数为个位数,说明问题是用户操作或手机异常引起的。在确定了问题的大体方向后,在没有办法检查代码的前提下,现在能做的就是重现问题。前面说了QuotaExceededError是内存溢出类型的错误。我的直觉告诉我,我需要找一台剩余内存空间最少的测试机,但当时最少剩余内存空间是20GB。于是下载了一天的大型软件,终于在内存剩余100MB左右的时候成功了。经常性的。问题的原因与浏览器会为localStorage预留大约5MB的存储空间不同。indexedDB的配额是动态计算的。准确的说,浏览器的存储配额是动态计算的。尽管浏览器有不同的实现,但它们可以使用的存储量通常取决于设备上可用的存储量。此可用存储量称为全局限制,对于Firefox约为可用磁盘空间的50%,对于Chrome约为80%。如果超过此限制,将启动称为源回收的过程,删除整个源的数据,直到存储再次低于限制。不存在只删除源数据的一部分这样的事情——因为这可能会导致不一致。除了全局限额之外,还有一个限额叫做团体限额——全局限额的20%。这里,每个二级域名都可以看作一个组,每个组最多可以聚合到全局限制的20%。如果超过组限制,或者原始回收进程无法释放足够的空间,indexedDB或缓存API将抛出一个名为QuotaExceededError的DOMError。如何查看可用的存储空间?如果(navigator.storage&&navigator.storage.estimate){constquota=awaitnavigator.storage.estimate();//quota.usage->使用的字节数。//quota.quota->可用的最大字节数。constpercentageUsed=(quota.usage/quota.quota)*100;console.log(`${percentageUsed}%的可用存储空间已被使用。`);constremaining=quota.quota-quota.usage;console.log(`最多${remaining}字节可以再次写入。`);}附言。该方法使用StorageManagerAPI,使用前必须检查其功能。实测时,Android的webview支持该方法,ios不支持。优雅降级的解决方法只是判断浏览器是否支持某种本地存储方式,并不能处理硬盘不足的问题,所以如果想避免这个问题,可以在业务代码捕捉异常,手动做异常处理。业务中常见的解决方案是弹窗提示用户清理手机硬盘。实测中,当华为手机的硬盘小于100MB时,系统层也会弹出清理手机的弹窗提示。try{localforage.setItem('key','value',doSomethingElse);}catch(err){if(err.name==='QuotaExceededError'){//异常处理}}总结&思考localforage是一个优秀的前端存放js库。从某种角度来说,indexedDB的发展得益于localforage。无论是localStorage还是indexedDB,存储空间都受浏览器的存储配额影响,而浏览器的存储配额取决于本地磁盘剩余空间的大小。配额不足会导致浏览器报QuotaExceededError。在开源轮盘找不到问题的时候,在代码仓库的issue中搜索将是一个捷径。笔者忽略了这一点,走了弯路。参考1.https://web.dev/storage-for-the-web/2。https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria3.https://www.zhangxinxu.com/wordpress/2018/06/js-localforage-localstorage-indexdb/