大多数应用程序将缺乏连接视为意外事件。您打开一个屏幕,网络消失,然后出现令人沮丧的警告:没有互联网,请重试。应用程序放弃了,用户也放弃了。
离线优先从头开始颠倒了这个逻辑。前提是,没有连接是正常状态,有连接是加分项。这不是悲观主义,而是现实主义。任何构建混合现场、移动或网络应用程序的人都知道网络失败的情况比我们愿意承认的要多。
将离线视为规则,而不是错误
差异始于设计师的想法。在常见的模型中,最好的路径是在线,而离线是一个不好的偏差,需要稍后处理,通常是很糟糕的。在离线优先中,快乐路径已经假设可能没有网络。
这一前提的改变改变了各级的决策。屏幕不能依赖远程调用来显示内容。用户操作不能挂起等待服务器的确认。该流程需要设计为在本地完成并稍后协调。
当你这样设计时,在线用户也会发生一些有趣的事情。由于一切都首先在本地响应,因此即使网络良好,体验也会更快。实际上,离线优先是本地优先哲学的超集,适用于最敌对的情况。
始终首先保存本地
该方法的核心是一个简单的规则:所有写入首先发生在设备上。该接口从该本地存储中读取并即时反映变化。用户永远不会等待服务器看到自己操作的结果。
在浏览器中,选择的存储通常是 IndexedDB。它是一个嵌入页面本身的[数据库1],能够存储大量结构化数据,并支持索引和查询。与更简单的解决方案不同,它处理真实应用程序的重量,而不仅仅是一些松散的偏好。
接口层现在将IndexedDB视为其读取源。服务器成为第二层,由同步提供支持。这种设计需要纪律,因为现在模具有两个地方,并且它们需要在用户不注意到接缝的情况下会聚。
在本机移动应用程序中,原理是相同的,只是存储技术发生了变化。重要的是规则:本地第一,远程第二。
同步队列及其详细信息
如果是离线写入,则需要稍后传送到服务器。这就是同步队列发挥作用的地方。每个更改数据的操作都被记录为挂起的意图,存储在本地,等待连接窗口上升。
看似简单,但细节决定成败。队列需要在应用程序关闭后继续存在。发送失败时需要重试,不能重复已发送的内容。您需要尊重操作顺序,因为创建记录然后编辑它是无法在服务器上交换的事情。
我建议尽可能将每个排队操作视为幂等。幂等性意味着重新提交相同的操作不会造成损坏。这使得同步细微错误的来源成为一个可预测的过程,因为您可以毫无恐惧地重试。
还有反向同步。当设备离线时,世界仍在继续:其他用户进行编辑,服务器发生变化。当连接恢复时,您需要进行这些更改并与本地状态合并。而合并是最棘手的问题出现的地方。
当两个设备编辑相同数据时
想象一下,两个现场代理离线打开相同的注册。一个更正地址,另一个更正电话号码。两者再次有信号并同步。哪个版本获胜?天真的答案,最后一个到达的答案覆盖了一切,让其中一个人默默地失去了工作。不可接受的。
解决冲突是任何认真对待线下优先的人的中心主题。最简单的策略(以时间取胜)适用于很少有争议的数据,但当竞争编辑涉及同一记录的不同字段时,就会严重失败。
更好的策略按字段合并,保留一个地址的更改,另一个保留电话号码的更改。对于更复杂的结构,CRDT 发挥作用,数据类型设计为在合并时自动收敛,而不需要中央仲裁器。在发明自己的合并逻辑之前,值得研究[CRDT 在实践中如何工作2],因为这是一个充满陷阱的领域。
我诚实的建议:不要将冲突视为罕见情况,并在项目结束时即兴发挥。尽早为每种类型的数据定义收敛规则。这一决策既是一项产品决策,也是一项工程决策,因为它定义了两个真实的人的工作会发生什么。
对使用者体验的影响
所有这一切的存在都是为了提供一种体验,并且其效果是巨大的。离线优先的应用程序以触摸速度而不是网络速度进行响应。对于那些在该领域工作的人来说,这就是可靠的工具和在最糟糕的时候失败的麻烦之间的区别。
但需要对用户诚实。由于同步是在后台进行的,因此您需要清晰的状态信号:发生了什么、待处理什么、是否出现问题。隐藏这一点会产生一种虚假的安全感,而虚假的安全感比公开的不安全感更糟糕。
优秀的离线优先应用程序可以毫无恐惧地进行交流。待决问题的谨慎指示器,冲突需要决策时的警告,一切同步时的平静确认。用户不需要了解工程学,但他们需要相信他们的工作不会消失。
团队应该从哪里开始
如果您领导的团队即将采用离线优先,请避免同时尝试所有事情的错误。从本地存储开始并从中读取。然后引入写入的同步队列。只有这样才能面对冲突,并通过数据类型来面对它,而不是以通用的方式。
还要抵制从头开始构建自己的同步引擎的诱惑。这是一个诱人而深刻的问题,但可以通过成熟的工具解决。了解[本地优先3就绪同步引擎的选项可以为你的团队节省数月时间。
离线优先并不是一种技术上的奢侈,而是一种尊重那些远离完美网络舒适的软件使用者现实的方式。那些以这一前提进行设计的人能够在最重要的时候提供持续经受住考验的产品。
另请阅读
- [现实生活中位置优先:政府、医疗保健和物流4
- [本地优先:首先在您的设备上运行的软件5
- [同步引擎:使本地优先可行的工具6
- [CRDT:如何同步 Serverless 数据来仲裁冲突7
- [何时使用 PWA8
- [混合应用程序什么是9?
