文章目录
写在前面
1.什么是协同编辑
多人同时编辑一个文档,能够在不刷新页面的情况下实时地看到他人的编辑。典型例子有石墨文档、腾讯文档、Google Docs等。
主要需要解决的技术难点有:
- 实时通信
- 编辑冲突
2.可选的解决方案
- 实时通信有long pull或者websocket
- 编辑冲突解决有合并算法、上编辑锁以及Google Docs采用的分布式OT。
- 编辑冲突问题交给用户,当前用户实时地看到了别人正在编辑,那么当前用户就自觉性地停止编辑。
3.仅仅使用websocket
本文旨在为敏捷开发中快速实现多人在线协同编辑的需求提供一种只使用websocket的简单方法,其特点可以总结为以下几点:
- 代码量少并且容易理解,实际运行效果也较好,适用于小项目敏捷开发
为了赶ddl快速达成展示效果。 - 后端甚至直接与数据库分离,作为一个仅仅用于实时通信的后端服务,舍弃了实时保存的服务,提高实时性。
- 将编辑冲突问题交给了用户,实际的编辑同步并发性基于websocket的响应速度。
4.示例项目框架
前端Vue+后端Flask+geventwebsocket+数据库MySql
文档编辑器采用mavon-editor
实现步骤
1.思路
因为仅仅使用了websocket,因此思路十分明确:
- 用户打开文档编辑页面,与后端建立长连接。
- 后端将当前用户加入当前文档编辑用户列表。
- 前端监听用户对于文档内容的修改,每一次修改将整个修改内容发送给后端。
- 后端接收到信息,不做任何处理,直接将文本信息发送给文档编辑用户列表中其他的所有用户。
- 前端收到后端的文本信息直接覆盖掉当前文档内容。
在websocket请求中存储有用户连接信息,发送接收是同一地址,可以使用request.environ.get('wsgi.websocket')
获取连接信息存入userlist中,直接进行监听以及发送即可。
在文档内容之外如果需要开发出其他的实时更新的消息可以使用json进行传输,标注各个信息在后端进行处理后再传输。当然处理多了会降低响应性。
经过实际操作,websocket传输似乎只支持字符串,所以前后端传输的必须是json格式的字符串,在发送前与接收后都需要相应的处理。
- 前端将json对象转为json字符串的语句是
JSON.stringify(jsonobj)
- 前端将json字符串转为json对象的语句是
JSON.parse(data)
- 后端(Python)将json对象转为json字符串的语句是
json.dumps(obj)
- 后端(Python)将json字符串转为json对象的语句是
json.loads(str)
实际运行发现后端json对象转字符串存在格式问题,前端不可读,所以直接手写json字符串解决。反正东西少,手写不烦
2.示例代码
实现了实时更新正在编辑的用户以及文本内容
并没有处理连接断开操作
每次传送的值包括:
“username”:当前用户用户名(数据库用户名唯一)
“content”:修改后的文档内容
(1)前端
全局函数
function contains(arr, obj) {
var i = arr.length;
while (i--) {
if (arr[i].username=== obj) {
return true;
}
}
return false;
}
判断用户列表有没有收到的用户,如果进行修改的是新用户,加入正在编辑的用户列表
websocket初始化
写在methods中
initWebSocket(){
//初始化weosocket
const wsuri = "ws://ip:端口/conn";