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

前段时间完整的看了云谦大佬分享的「前端框架的趋势与实践」的视频。看到有关数据流的请求方案即数据流满足大量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采用的解决方案是回调,回调中接受上一个状态。

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

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

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

小结

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

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

相关推荐
一 乐4 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
昨天;明天。今天。4 小时前
案例-表白墙简单实现
前端·javascript·css
安冬的码畜日常4 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
小御姐@stella4 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing4 小时前
【React】增量传输与渲染
前端·javascript·面试
GISer_Jing4 小时前
WebGL在低配置电脑的应用
javascript
万叶学编程7 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js
天涯学馆9 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF10 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss