前端必须实现操作队列、版本校验与本地暂存,配合服务端OT/CRDT协同,否则多人编辑必丢数据或覆盖错误——WebSocket只传不管对错。
前端不做冲突处理,就一定会丢数据或覆盖错内容——WebSocket只管传,不管对错。
为什么直接用
覆盖全文会出问题
很多快速实现方案(比如 Flask + Vue 简单广播)让每个编辑操作都把整个文档内容发过来,前端收到就
。这在单人编辑时没问题,但两人同时改:A删了第3行,B在第2行末尾加了字,谁后到谁赢,先到的操作被彻底抹掉。
浏览器没有“操作队列”概念,
是原子覆盖,不保留任何上下文
网络延迟导致消息乱序,后发的操作可能先到,前端无法判断该不该应用
用户本地光标位置、选区状态全丢,强行覆盖后体验断裂
和
必须带位置与版本校验
真正可落地的前端同步,得把“用户做了什么”拆成最小可逆操作,并附带执行前提。不能只传结果,要传动作 + 上下文。
服务端推送的消息必须含
字段,如
或
前端收到后,先比对本地
:若
,直接丢弃(已过期);若 >,再检查
是否仍在有效范围内(防因前面操作导致偏移错位)
编辑器需支持底层操作调用,比如 CodeMirror 6 的
,Monaco 的
,而不是走
这种高层封装
前端必须维护本地操作暂存与回滚能力
用户正在输入时 WebSocket 断连,重连后不能只靠服务端补发——那些未发出的本地操作必须还在,且能和补发操作合并重放。
面向设计的AXUI前端框架表单
面向设计的AXUI前端框架表单是一款包含表格、列表、弹窗等的AXUI前端框架表单下载。
下载
立即学习
“
前端免费学习笔记(深入)
”;
每次键盘输入触发的操作,先存进一个
队列,同时打上本地时间戳和随机
连接断开时,暂停发送,但允许用户继续编辑;重连后,先发
给服务端做 OT 合并,再接收服务端返回的权威状态
服务端返回的同步消息里如果含
,说明你的本地操作已被转换,前端要按新
重算并应用,不能硬套原位置
光靠前端永远不够:必须和服务端 OT/CRDT 协同
前端所有“校验”“暂存”“重算”都只是防御性措施,最终一致性锚点永远在服务端。你看到的
、
、
全是服务端生成和裁定的。
不要自己实现 OT 变换函数——Java 后端用
或
,Node.js 用
,它们输出的
结构前端才能安全消费
前端收到的每条消息,都应有服务端签发的
,用于和本地操作排序,而非依赖
最易忽略的一点:前端必须监听
,把未提交的
存 localStorage,否则刷新页面就真丢了
onmessageeditor.setValue(newContent)setValueinsertTextdeleteTextop{"type":"insert","index":42,"text":"OK","version":12}{"type":"delete","index":42,"length":2,"version":12}versionmsg.version <= localVersionindexview.dispatch()executeEdits()setValue()pendingOpsclientId{"type":"sync:pending","ops":pendingOps}rebase:trueindexversionrebaseclientIdsharedbottypesot-json0opserverTimestampDate.now()beforeunloadpendingOps