这些是问题的步骤
- 数据的初始状态,包含重要索引的列表
- 更改列表中项目的索引
- 更新列表中所有项目的操作
- 数据的最终状态
至少有 3 种方法可以在客户端和服务器之间同步 #1 和 #4,我将在下面概述。请注意,我不会比较这三个选项的计算强度。听起来,处理速度不是您最关心的问题,而是带宽是。考虑到这一点,以下是三个选择:
方法一:发送最终状态
第一种方法是最明显的方法,也是您遇到问题的方法,是通过传递 #4 来更新服务器。随着您的列表变长,这将成为发送的相当大的有效负载。
Pros
- #3 执行一次
- 它适用于最常见的 HTTP 动词,例如 POST
- 这是最明显的;很容易理解发生了什么
Cons
- 正如您所指出的,随着列表的增长,您通过线路发送的数据会变得非常大
方法二:仅发送更改
第二种选择将带宽降低到绝对最小值。为此,您可以通过线路传递#2 并在服务器上执行#3。这会重复该操作(我想您仍然希望在客户端上执行它,而不是等待服务器的响应),但将带宽使用保持在最低限度。
这可能如下所示:
{
oldIndex: 2134
newIndex: 54
}
这为服务器提供了执行 #3 和执行 #4 所需的一切。这很容易扩展到n
通过创建按顺序执行的操作列表来进行操作,从而产生n
更新中的对象。
Pros
Cons
- 客户端和服务端重复操作逻辑,不太DRY
- 服务器执行更多计算
- 它是专有的,不像第一种方法那样简单的 API 端点
方法三:JSONPatch
第三个选项是使用JSON 补丁规范 https://www.rfc-editor.org/rfc/rfc6902生成补丁发送到服务器。单个移动操作的 JSON 补丁产生n+1
物体,其中n = Math.abs(oldIndex - newIndex)
.
例如,
给定初始数组
[a, b, c, d, e, f, g, h, i, j]
和操作
{
oldIndex: 5
newIndex: 2
}
上面的算法显示 JSONPatch 将有 5-2+1,即 4 个对象。这些对象是:
[
{"op":"replace","path":"/5","value":"e"},
{"op":"replace","path":"/4","value":"d"},
{"op":"replace","path":"/3","value":"c"},
{"op":"replace","path":"/2","value":"f"}
]
如果您选择使用 JSONPatch 我建议您使用类似的库JSON 补丁 https://github.com/Starcounter-Jack/JSON-Patch来处理它。
Pros:
- 处理的不仅仅是动作
- 没有库可以处理所有的边缘情况(我在 JSON-Patch 上有几个关于失败情况的未解决问题)
Cons:
- 比仅仅传递操作本身更多的带宽
- 潜在的更多计算
- 需要额外的库
- 取决于 HTTP PATCH 动词