平衡SPA中的响应能力和状态一致性

发布于:2021-01-13 10:21:20

0

151

0

平衡SPA 响应能力 状态

构建现代Web应用程序时要解决的有趣技术挑战之一是,根据有时缓慢的API端点,如何为UI实现可接受的响应能力。

用户对应用程序缓慢的感知完全取决于延迟,反应,等待时间和反馈。延迟,冻结,反馈滞后,无响应-所有这些都会使您的产品感到沉重。有一篇很棒的文章总结了软件世界中缓慢意味着什么。

在API方面,slow的定义可能会有所不同,但我们假设单个请求往返的时间超过100毫秒。即使对于不涉及数据库的简单方法,优化和压缩响应时间也不是一件容易的事。涉及到许多增加的延迟层:网络延迟,安全套接字和加密,反向代理,平衡器,数据库,高速缓存命中率等。这是一个单独的广泛主题,是一个很好的实验领域。

现代的单页应用程序(SPA)取决于API延迟以及所需的桌面体验,您需要更快的API响应。但是,与任何客户端服务器应用程序一样,您应该期望延迟,延迟和连接丢失。API响应缓慢且中断是设计Web应用程序时应采取的核心假设。在这里,可以使用一些简洁的SPA模式。

让我们举一个简单的例子。想象一下,我们正在构建一个简单的待办事项SPA,用户可以在其中添加项目,然后将其状态更改为已完成。

{xunruicms_img_title}

有很多可能的UX场景,但是在我们的示例中,我们假设按下加号按钮会添加一个新项目,然后我们可以对其进行编辑或标记为已完成。因此,按下按钮会立即创建一个项目,并且不需要用户执行其他任何操作。对于我们的示例应用程序,添加项目需要向API发送单个POST请求。幼稚的方法是发出请求,等待诺言履行,然后更新视图(或状态,如果使用类似redux的体系结构)。毫不奇怪,这会立即导致等于API请求往返时间的延迟。延迟的一个小借口可能是微调器或其他正在进行的指示器。

有办法避免这种令人沮丧的经历吗?当然。SPA应用程序的一种广泛使用的方法是使用虚拟对象,这些对象可以立即创建,然后替换为具有来自后端的ID的真实对象。

{xunruicms_img_title}

这个小技巧完全解决了延迟问题。用户在行动和结果之间不会出现明显的延迟。权衡是显而易见的:出现问题时,您新创建的商品将消失。或者,更糟糕的是,您将继续与之交互,并期望关闭选项卡后不会保存任何内容。但是,让我们假设这是一种例外(因此很少见)的情况。如果后端方法失败,您总是可以向用户发出温柔的通知,警告他某些地方出了问题,并且您的商品将无法保存。此外,您可以在惊慌之前以静默方式重试一次或多次。但是,让我们来看一个更复杂的示例:

{xunruicms_img_title}

这次,新的UI交互在中间发生,更改了item属性,同时解决了API请求承诺,并且没有用真实的对象替换虚拟对象。简单地忽略这种情况将导致UI损坏,用户困惑并可能导致错误的输入。

我不知道针对上述问题的可靠解决方案,这些解决方案在UX的某些方面(响应性,对应用程序的感知为快速,冻结,阻塞)或可靠性(意外地恢复或丢失更改)不会受到影响。那是我们应该决定响应能力和状态一致性之间的平衡的地方。对于上面的示例,我们可以简单地决定阻止与虚拟对象的任何交互,直到将其替换为真实对象为止。或者使用待处理状态,队列等构建更复杂的状态突变逻辑。

当交互涉及多个对象时,事情变得更加复杂。以前面的示例为例,如果我们想更改项目的顺序,交换项目B并仍然虚拟项目C,该怎么办:

{xunruicms_img_title}

这次,替换虚拟项目将覆盖属性更改,并使应用程序状态无效(并且与后端不一致)。那么,如何解决冲突的状态更改?首先,不要应用导致状态不一致或损坏的状态突变。在前面的示例中,我们可以逐字段进行比较,而忽略权重值的变化。其次,我们可以记录即将发生的更改,并仅应用不更改的属性。与第一种方法相比,这是一种更为复杂的方法,但是它更具通用性和可靠性。

应该有更成熟的模式来解决SPA中的响应性问题,当有任何有趣的事情出现时,我将尽力介绍它们。

最后,我还没有涉及多个用户的并发场景,这本质上是一个完全不同的主题,涉及分布式系统,例如共识算法等。