JavaScript中两个字符串之间的网络效率差异

3
我有一个Web应用程序,在客户端编辑器中编辑一个非常大的文本,服务器端已知该文本。
客户端可以对此文本进行任何修改。
在网络效率最高的情况下,以一种服务器能够理解的方式传输结果差异是什么?此外,由于这将发生在客户端(Javascript)上,我也希望它是“快速”的(或者至少不会明显变慢)。
一些场景:
- 用户修改一个字符 - 用户在随机位置修改了几个句子 - 用户删除所有内容并导致空白文本。
我不能使用类似diff的语法,因为它不是网络有效的,它检查行,其中示例1和3将产生可怕的差异(特别是最后一个,其中结果将比旧的自身更多)。
有没有人在这方面有经验?用户操作的数据集非常大 - 大约3-5MB的文本,上传整个“新”内容是绝对不行的。
明确一点,我正在寻找一种传输“协议”,字符串比较不是问题。

你可以使用不同的工作方式。当页面加载时,你可以将文本的副本保存在内存中,然后允许编辑。在发布之前,你可以进行差异比较并发送该信息。 - BobbyShaftoe
如果我使用diff风格,当用户更改一个字符时,整个行都会被区分出来。如果所有内容都被删除,则会得到完整的 -- 语句块,这些块比原始内容更大,具体取决于换行符数。 - LiraNuna
5个回答

3

我对这个话题不是很熟悉,但我可以指向一个开源(Apache License 2.0)项目,可能非常有用。

它是一个差异、匹配和修补库,使用多种语言编写,包括JavaScript,由Google工程师编写,并在多个在线协作编辑服务中使用。

以下是一些资源列表:


是的,Google Tech Talks 有很多隐藏的宝藏。我订阅了他们的 RSS 源[1],这就是我偶然发现这个迷人而深入的演讲的原因。[1]: http://gdata.youtube.com/feeds/base/users/googletechtalks/uploads - brianpeiris

1

一个简单的方法,假设您知道服务器上的副本不会更改,就是发送编辑列表(删除和添加),其中删除表示为开始和结束索引,添加表示为开始索引和要插入的文本。

如果您有更多的比较算法可用(我不确定您所说的“字符串比较不是问题”具体指什么),您还可以检测移动或复制的文本块,并将其作为移动或复制的文本块的起始和结束索引以及要插入的目标发送。

请注意,您需要确保跟踪您的索引是指原始文档还是到目前为止已编辑的文档。避免此问题的简单方法是始终从文档末尾向文档开头执行编辑;然后早期的编辑不会影响后期编辑指定的偏移量。

举个类似这种方法的例子,可以查看 diff -e 输出的 ed 格式。这基本上是可以输入到ed 行定向文本编辑器中的输入。如果你想要传递最小的差异,可能需要进行基于字符的索引而不是基于行的索引,但是同样的基本方法可以奏效。


1

用户执行的任何编辑都可以有效地分解为:从X删除长度为Y的内容;在X处插入文本“whatever”。X和Y是从文本开头开始的字符偏移量;Y是一定数量的字符;“whatever”是任意字符串。你说你不需要帮助计算差异,但这里有一个例子here,它的输出比你需要的更丰富,但确实识别了“删除和插入”,所以只需更改输出部分即可。

向服务器发送数据的确切格式可以进行调整,但我认为没有太多的收益-在测量之前,我会从发送D表示删除或I表示插入的命令开始,使用十进制数字,插入的字符串用引号括起来。一旦您获得了实际传输的统计数据,您就可以看到数字(十进制与二进制)和引号中有多少开销,但我怀疑这可能并不是非常有意义的(如果证明是这样的话,您可以尝试各种方法,例如从最新的插入或删除点给出偏移量,而不总是从开头开始,以使事情更快)。

你可以每隔几秒钟采样一次用户正在做什么,然后只发送这些最近几秒钟的增量更改(如果有的话)-- 这样,你发送的每个数据包都会很小,如果网络连接或用户的计算机/浏览器崩溃,用户不会失去太多工作。

0

你可以每500毫秒发送一次更改,因此在过去的500毫秒内进行的任何更改都将被发送,但仅在有更改时才发送数据。

在此过程中,您可以发送更改单词的位置并只发送整个单词,但我建议将位置从文本前面开始计算。

这可能不会涉及几个句子,但可能涉及几个单词,但是,如果按更改顺序发送它们,则结果应始终如一。


如果用户剪切了文档的前半部分并将其粘贴到后半部分下面,会怎样? - Kev
剪切和粘贴是两个操作,因为在500毫秒内同时完成两个操作不太可能。 - James Black

0

因为编辑有很多种方式——即使在短时间内(如500毫秒)内,包括拖放、剪切和粘贴文档内或外的大段文本——所以我不知道是否会有一种方法能够很好地覆盖所有情况。从表面上看,这显然不是你问题的答案,但我建议你仔细考虑开发和维护这样的事情相比于改变界面以限制文本大小并将现有文本分成较小的部分所带来的困难。

也许在你的情况下这不可能,但如果可以的话,我猜最终规避这个问题并只在编辑后发送完整的文档会更加简单。


这不是实时的,我需要比较两个大字符串 - 服务器知道原始字符串,客户端更改了一个。用户完成后将按下按钮。 - LiraNuna
我知道,我是在评论其他人提出的解决方案,即通过短时间间隔监视用户正在做什么,以便更容易地计算差异。我的意思是说,你可以使计算差异变得复杂,但几乎可以立即完成。 - Kev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接