翼度科技»论坛 编程开发 JavaScript 查看内容

codemirror diff-match-match 不同设备、不同设备状态下的对比结果不稳定

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
今天遇到一个问题,在使用codemirror对两条文本内容进行对比时,有同事反馈在它的电脑上会显示成:前面一半是正常显示差异内容,而后面就变成了全部是新增的。
像这样:

预期的对比结果是这样:

我们观察用于对比的两个文本,实际上上面的文本都是去掉后面括号中的内容,对比结果不应该表现成全部删除全部新增。
于是我开始在本地尝试复现,很不幸,有时候可以,有时候不行
接着我开始查找codemirror使用的对比库,diff-match-patch,这个库的对比方法的构造函数如下:
  1. /**
  2. * Class containing the diff, match and patch methods.
  3. * @constructor
  4. */
  5. var diff_match_patch = function() {
  6.   // Defaults.
  7.   // Redefine these in your program to override the defaults.
  8.   // Number of seconds to map a diff before giving up (0 for infinity).
  9.   this.Diff_Timeout = 0.5;
  10.   // Cost of an empty edit operation in terms of edit characters.
  11.   this.Diff_EditCost = 4;
  12.   // At what point is no match declared (0.0 = perfection, 1.0 = very loose).
  13.   this.Match_Threshold = 0.5;
  14.   // How far to search for a match (0 = exact location, 1000+ = broad match).
  15.   // A match this many characters away from the expected location will add
  16.   // 1.0 to the score (0.0 is a perfect match).
  17.   this.Match_Distance = 1000;
  18.   // When deleting a large block of text (over ~64 characters), how close do
  19.   // the contents have to be to match the expected contents. (0.0 = perfection,
  20.   // 1.0 = very loose).  Note that Match_Threshold controls how closely the
  21.   // end points of a delete need to match.
  22.   this.Patch_DeleteThreshold = 0.5;
  23.   // Chunk size for context length.
  24.   this.Patch_Margin = 4;
  25.   // The number of bits in an int.
  26.   this.Match_MaxBits = 32;
  27. };
复制代码
看到这个bug,我首先怀疑是由于阈值,所以尝试修改 Diff_Threshold 和 Match_Distance 尝试将它们调小,看是否能够复现。很不幸,也不行。
接着我又去查了 diff-match-patch的文档
注意到了 Diff_Timeout这个参数,文档中解释了为什么会有这个参数,主要是为了避免对比所耗费的时间,默认值是1s,超过1s为完成对比,剩余部分就会以新增/删除来返回。
引用一段文档中的解释:
尽管此函数中使用了大量优化,但diff的计算可能需要一段时间。Diff_Timeout属性可用于设置任何Diff的探索阶段可能需要多少秒。默认值为1.0。值为0会禁用超时,并让diff运行直到完成。如果diff超时,返回值仍然是一个有效的差值,尽管可能不是最佳值。
所以这个bug不一定所有人的设备都能复现,即使是同一个的设备,在不同的设备状况(cpu使用率、内存占用)等情况下,也会有区别。在知道原因后,通过手动修改 Diff_Timeout 的值来尝试复现bug就能成功了。
那么如何解决呢,根据文档,我们可以设置一个较大的超时时间,来确保diff可以完成。或者设置为 0这样就会让diff运行直到结束。实际代码可以通过对DiffMatchPatch构造函数做一层包裹来实现:
  1.   window.diff_match_patch = function () {
  2.     const dmp = new DiffMatchPatch()
  3.     // https://github.com/google/diff-match-patch/wiki/API#diff_maintext1-text2--diffs
  4.     // 设置超时时间为0,禁用超时设置,直至diff运行结束
  5.     dmp.Diff_Timeout = 0
  6.     return dmp
  7.   };
复制代码
来源:https://www.cnblogs.com/azoux/p/18343141
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具