前端数据流的新趋势——乐观更新

前段时间完整的看了云谦大佬分享的「前端框架的趋势与实践」的视频。看到有关数据流的请求方案即数据流满足大量CRUD场景趋势的时候,我注意到云谦大佬提到了一个关键词------乐观更新。

抱着求知的态度进行自我探索,我特意进行了一番Google,发现有关乐观更新的文章寥寥无几,而且看完之后依然"云深不知处",所以我打算将我对于乐观更新的学习心得分享出来,希望能对感兴趣的小伙伴有所帮助。

乐观更新是什么

我们进行页面渲染的时候,通常是进入页面先发起请求从服务端获取相应的数据,然后根据服务端返回响应数据之后再去进行视图更新。而在请求的过程中,需要消耗一定的时间来等待服务端的响应,为了防止用户跳出,我们通常会给用户一定的反馈,保证用户知道当前数据正在处理中。为了给用户提供更好的体验,比较常见的做法就是给用户显示一个loading的菊花图,表示当前正在数据请求中。

而乐观更新正式对这个环节继续了调整,追求更快的渲染速度,当请求发起之后,直接按照心里预期进行页面渲染,而不等待请求的完成。

乐观更新的分析

乐观更新虽然有助于提升用户体验,但是我们绝对不能盲目乐观。我们要对乐观更新有清醒的认识,然后在正确的场景运用它,充分发挥乐观更新的优势。 如果错误的使用了乐观更新的话,不但起不到提升用户体验的效果,反而会降低用户的粘性。

乐观更新的优势

乐观更新可以大幅提升用户体验,并在第一时间与用户进行交互,可以增加用户的粘性。

乐观更新的劣势

  • 乐观更新对网络请求的成功性有要求,需要保证请求的失败率极低;
  • 乐光更新使用场景有限制,更偏向于展示性交互或者单一性操作;
  • 乐观更新需要可逆,如果请求异常之后,需要进行及时修正;

乐观更新的应用场景

基于乐观更新的特性,对比较适合使用乐观更新的应用场景进行了分析,找到了几个比较适合的场景:

  • 论坛类数据
  • 聊天消息的发送、撤销、删除
  • 列表类数据的增删查改

我们进行乐观更新的时候,是基于请求大概率成功的前提下,所以说乐观更新存在着失败的可能性(虽然可能性非常低)。当请求异常时,我们需要重新进行获取数据,对现有乐观更新的数据进行修复;如果重新获取不到的话,我们就要对数据进行回滚操作。

乐观更新的伪代码

我们使用微信发送消息的时候,消息发送之后,会第一时间显示在客户端;如果消息发送失败,微信会将消息的状态更新为发送失败状态;如果消息发送成功,客户端没有变化。我们就基于这样的场景,通过伪代码来实现一下消息的乐观更新,辅助理解一下。

我们先来实现一下发送成功的交互,当用户点击发送之后,我们进行乐观更新消息内容,这里我们并不会使用async await 或者 Promise 对消息发送请求进行等待。

JavaScript 复制代码
    function sendMsg () {
        // 获取当前数据的上下文(伪代码)
        const ctx = getContext();

        // 保存历史数据的快照
        const previousMsgs = ctx.getMsgList();

        // 发送消息,异步处理
        ctx.sendMsg()
            .then((err) => {
              if (err) {
                ctx.rollback(err, previousMsgs);
              } else {
                ctx.commit(newMsg);
              }
            });

        ctx.updateMsgList((msgList) => ([...msgList, newMsg]));

        return { previousMsgs }
    }

前面我们说了,乐观更新存在着一定的失败几率,所以我们需要实现一个容错机制,用来做消息的查询或者回滚,保证我们请求异常时能够将数据修正。

JavaScript 复制代码
    function handleError(previousMsg) {
        try {
          // 重新进行数据查询
          const msgList = getMsgList();

          this.updateMsgList(msgList);
        } catch (error) {
          // 查询失败,直接进行回滚
          this.updateMsgList(previousMsgs);
        }
    }

我们将两步组合到一起,就是乐观更新的伪代码。

JavaScript 复制代码
  useOptimistic(msgList, sendMsg, handleError);

但是,还有一个很重要的问题那就是更新时序问题

使用过React的小伙伴,应该知道React在进行setState的时候,也存在着时序的问题,只不过React采用的解决方案是回调,回调中接受上一个状态。

对于我们乐观更新也存在着同样的问题。我们进行前后端数据通讯的时候,响应的先后顺序取决于多个因素,但绝对不是完全按照发送的先后顺序依次响应的。那这也就意味着,我们对于同一数据进行操作时,存在先后顺序异常的情况。所以我们需要对同一数据的操作进行干预,以防止数据最终状态不是我们期望的。

一种方式是同一时间只允许一个操作任务进行(不可取,满足不了实际需求)

另外一种方式是,我们实现一个更新队列(先进先出的机制),在操作的时候将任务推入到更新队列中,等待前一个任务出队之后再执行下一个任务,直到任务完全出队。

小结

虽然,现在没有现成的轮子来实现乐观更新,但是我相信,随着大家对用户体验的极致追求,乐观更新会普及到更多的业务开发过程中。虽然实现起来有一定的技术难度,但是带来的产品价值也是十分可观的。

最后,希望上面的内容对大家有所帮助。

相关推荐
前端小白佬23 分钟前
【JS】事件传播--事件捕获/冒泡
javascript·面试
PasserbyX33 分钟前
ES6 WeakMap 生效的证明: FinalizationRegistry
前端·javascript
努力学习的小刘36 分钟前
如何使用react-router实现动态路由
前端·javascript
PasserbyX36 分钟前
JS原型链
前端·javascript
Danta41 分钟前
从0开始学习three.js(1)😁
前端·javascript·three.js
我的心巴42 分钟前
vue-print-nb 打印相关问题
前端·vue.js·elementui
coderYYY1 小时前
element树结构el-tree,默认选中当前setCurrentKey无效
前端·javascript·vue.js
GISer_Jing1 小时前
Three.js中AR实现详解并详细介绍基于图像标记模式AR生成的详细步骤
开发语言·javascript·ar
GISer_Jing2 小时前
[总结篇]个人网站
前端·javascript
ss.li2 小时前
TripGenie:畅游济南旅行规划助手:个人工作纪实(二十二)
javascript·人工智能·python