DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS

Lodash truncate 一直不返回,separator 正则可能零宽匹配

Lodash 4.18.1 的 truncate 正则循环遇到空匹配可能不推进 lastIndex。按文本需求采用字符串或明确消耗字符的分隔条件,不在服务线程中执行死循环回归。

_.truncate() 调用后一直不返回,Node 进程的一条线程持续忙碌,而输入字符串并不长。若 options.separator 使用了可能零宽匹配的正则,先撤下这条截断路径,避免在服务请求中反复重现阻塞。

Lodash 4.18.1 的一个具体触发模式是 /(?<=,)\s*/。它在逗号后的空白长度为零时仍能匹配,却不消耗字符。用于展示故障的调用形态如下,不适合直接放进在线服务做探测:

const text = 'a,b' + 'X'.repeat(200);
const options = {
  length: 30,
  separator: /(?<=,)\s*/,
};
// 受影响版本对这组 text/options 调用 _.truncate 可能不返回。

正则循环没有推进零长度匹配

4.18.1 的正则分隔分支会把非全局正则转换成全局形式,再反复调用 exec() 找最后一个分隔位置。对于空匹配,循环没有主动推进 lastIndex,下一次仍可能停在同一位置。

因此,只给正则加 g 不能修复。外层的 Promise.race 或 setTimeout 也无法抢占这次同步循环:事件循环被占用时,定时回调本身就没有机会执行。

换成符合文本约定的分隔条件

如果需求只是尽量在逗号处分段,可以采用明确的字符串 separator:

import _ from 'lodash';

const preview = _.truncate(text, {
  length: 30,
  separator: ',',
});

字符串分隔会改变截断边界,应先确认逗号是否应被保留、原来的省略号与长度规则是否符合界面要求。若业务只需要空白分词,可考虑确实消耗至少一个字符的已知模式,例如 /[ \t]+/;它不等价于“逗号之后允许零个空白”,不要不经需求核对就替换。

这里没有要求放弃全部正则,只是不能把可能空匹配的模式交给受影响循环。用 regex.test('') 检查一次也不充分:带前后文断言的正则可以只在非空字符串的某个位置产生空匹配。任意用户输入的正则还可能有其他复杂度问题,不能靠这项检查当成通用安全过滤器。

Lodash 4.18.1 的正式实现中,这个循环仍没有零长度匹配推进保护。自行把社区补丁复制进 node_modules 容易在重装后消失,也需要另行核对 Unicode、正则状态与边界处理,不宜当成稳定维护方案。

采用明确分隔方案后,在隔离环境用较短与较长文本、没有分隔符、分隔符恰好落在截断位置,以及含非 ASCII 字符的输入核对结果。需要对旧故障做回归时,应放在可由外部进程终止的独立工作进程中,设置真实进程级时限,不在共享服务线程中等待“它应该很快结束”。