基于indexDB的web离线方案,APP断网也能用

需求背景

公司一个涉及到公路巡检的移动端项目,客户提出在有些情况下,比如隧道附近巡检时网络很差,甚至完全没网,客户之前选择的是拍照巡查完后补录相关信息,但还是希望这种情况也能够使用我们软件进行实时上报。虽然一直在吐槽产品为啥接了这个需求,但身为一个工具人还是只能老老实实寻求解决方案。

技术选型

要实现弱网能使用,其实就是做离线使用功能,如果时缓存本地,有网时上传到服务器。那么现在就是要考虑怎么做本地缓存。

前端本地缓存有4种方式:cookie、localStorage、sessionStorage、IndexedDB

在此种需求下,选择哪种唯一考量的就是存储容量,cookie最大只有4KB,storage各家浏览器不太相同,一般不超过有10MB,IndexedDB无上限,但和硬件有关。考虑到系统中有很多地方是上传图片,甚至有视频的可能,唯一的选择只有IndexedDB

IndexedDB 是浏览器提供的本地数据库,它可以被网页脚本创建和操作。允许储存大量数据,提供查找接口,还能建立索引。具有以下特点(网上抄的):

  • 键值对储存。 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
  • 异步。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
  • 支持事务。 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
  • 同源限制 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  • 储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
  • **支持二进制储存 ** IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。
    关于IndexedDB 具体增删改查API就不过多介绍,这里主要讲下方案和业务流程,以及踩的坑。

离线方案

简单描述就是先把后端数据存入IndexedDB,然后把从后端取值的操作都改为从IndexedDB中取,保存时也存到IndexedDB中,然后进行手动上传到后端。其实就是把数据库移到前端,然后前端实现后端的增删查功能。不标准的业务流程图如下:

image.png

第一步,数据下载

首先要整理出哪些数据是从后端获取,比如字典等一些下拉选项。然后在网络良好情况下统一请求后端接口,创建IndexedDB数据库和对象仓库,请求完毕后把不同类型数据写入不同的对象仓库中。

第二步,使用数据

使用数据一般都是在填写表单场景,填写前会进行当前网络情况判断,根据我们的业务如果是4g以下或断网,都认为是弱网环境,此时页面头部会有相应提示,里面的动态数据也从后端取值改为本地IndexedDB的对象仓库中取。

第三步,存储数据

表单填写保存时,会再创建一个对象仓库,用于存储当前表单信息,保存成功后提示已保存到草稿箱。草稿箱是用于展示和手动上传表单数据的功能模块。

第四步,手动上传数据

手动上传需要进入到草稿箱,进入后是已保存本地的数据列表,可进行删除和上传操作,删除是删除本地数据,上传需要在网络良好情况下使用,上传到后端服务中。

问题项

  • 弱网下无法访问相关页面

为了减少首次加载时间,路由配置时都使用的import异步加载方式,这样可以减少首页的打包体积,提高加载速度。但是如果想离线访问,就必须取消异步加载方式,直接引入对应组件。

  • 数据库删除失败

为了让每次数据下载都是新数据,如果进行对比更新太麻烦,选择的方案就是直接把数据库删除再重新创建,重新写入数据,但调用删除API时经常不生效。解决方式就是要先调用API关闭数据库,再执行删除操作。

  • 数据写入偶尔失败

数据下载时中途退出页面,再进入下载可能会异常无法再次写入数据。解决方式判断当前写入是否完成,如果未完成再退出时做二次确认提示,如果继续退出则一定要关闭数据库再退出。

  • 筛选联合查询

有的数据需要根据筛选项进行关联查询,此时就要用到IndexedDB的索引,比如需要根据id查询一条数据,那么在创建对象仓库时,同时创建id索引,使用时就可以使用对应API直接查询到对应数据。如果有更多筛选条件的,可以创建多个字段的联合索引。还有更特殊的比如一个字段查询符合编号或者名称,实现方式是先拿到对应所有数据,然后通过js匹配方式获得符合查询条件的数据。

  • APP中的离线访问

上面一切操作的前提是首先要在有网情况下打开一个页面,这样才能访问其它路由,但是在我们这个项目中,使用的是原生安卓套壳H5页面开发,而且首页多个菜单入口是由APP端开发,产品要求进入首页后,网络不佳也能离线使用一些表单填写模块。解决方式就是在项目打包时,资源打包为相对地址放到APP文件目录中,菜单入口配置为本地地址访问。这里注意一定不要在项目中使用cookie存储数据,因为本地访问方式不支持cookie取值。

  • APP后台进程杀掉或者重新登录账号数据丢失

这是开发完毕后发现的最大一个坑,猜测应该是每次在APP打开H5页面时,都实例化了一个webview,当后台进程杀掉或者重新登录时,再打开H5页面是又重新实例化一个webview,导致上次IndexedDB存储数据被销毁。但考虑到用户实际使用时,都是当前任务完成后才清空后台,就没有继续深入探讨,准备实际使用后根据反馈后果调整。

写在最后

上面就是第一次使用IndexedDB做离线功能的总结,首次尝试,特别是放在APP中使用时,因为欠缺此方面经验,真的是跳出一个坑又进入新坑。回头看来不由得思考,花了大量时间开发的离线功能,对客户真的是必要吗,收益和成本成正比吗?最后文章有不足之处还请各位大佬担待指出。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值